summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--CHANGELOG.md14
-rw-r--r--Cargo.toml3
-rw-r--r--source/benoit/benoit.rs1
-rw-r--r--source/benoit/benoit/application.rs26
-rw-r--r--source/benoit/benoit/application/animate.rs85
-rw-r--r--source/benoit/benoit/application/colour.rs2
-rw-r--r--source/benoit/benoit/application/draw.rs13
-rw-r--r--source/benoit/benoit/application/dump.rs12
-rw-r--r--source/benoit/benoit/application/handle_keys.rs51
-rw-r--r--source/benoit/benoit/application/initialise.rs43
-rw-r--r--source/benoit/benoit/application/loop.rs76
-rw-r--r--source/benoit/benoit/application/render.rs37
-rw-r--r--source/benoit/benoit/application/render_row.rs68
-rw-r--r--source/benoit/benoit/application/run.rs17
-rw-r--r--source/benoit/benoit/configuration.rs7
-rw-r--r--source/benoit/benoit/configuration/default.rs11
-rw-r--r--source/benoit/benoit/configuration/load.rs10
-rw-r--r--source/benoit/benoit/video.rs34
-rw-r--r--source/benoit/benoit/video/initialise.rs42
-rw-r--r--source/benoit/main.rs9
21 files changed, 448 insertions, 114 deletions
diff --git a/.gitignore b/.gitignore
index b1f83ce..0c44697 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
*.png
*.webp
/old
+/render
/target
Benoit.toml
Cargo.lock
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 689d22c..41835d5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,17 @@
+# 1↊
+
+* Use arbitrary-precision calculations
+* Depend on Rug
+* Optimise renderer
+* Animate if configured
+* Update commenting
+* Remove scale option from configuration
+* Auto-deduce thread count
+* Update controls (only render on command)
+* Update messages
+* Refactor application structure
+* Print controls
+
# 19
* Update controls
diff --git a/Cargo.toml b/Cargo.toml
index c89e85c..cb5072e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "benoit"
-version = "0.21.0"
+version = "0.22.0"
authors = ["Gabriel Bjørnager Jensen"]
edition = "2021"
description = "Mandelbrot renderer."
@@ -15,6 +15,7 @@ path = "source/benoit/main.rs"
lto = true
[dependencies]
+rug = "1.20.1"
sdl2 = "0.35.2"
toml = "0.7.6"
webp = "0.2.5"
diff --git a/source/benoit/benoit.rs b/source/benoit/benoit.rs
index d7deab8..f3d5299 100644
--- a/source/benoit/benoit.rs
+++ b/source/benoit/benoit.rs
@@ -23,3 +23,4 @@
pub mod application;
pub mod configuration;
+pub mod video;
diff --git a/source/benoit/benoit/application.rs b/source/benoit/benoit/application.rs
index 51d0602..ad5964a 100644
--- a/source/benoit/benoit/application.rs
+++ b/source/benoit/benoit/application.rs
@@ -21,16 +21,19 @@
If not, see <https://www.gnu.org/licenses/>.
*/
-extern crate sdl2;
+use crate::benoit::video::Video;
-use sdl2::{Sdl, VideoSubsystem};
-use sdl2::render::WindowCanvas;
+extern crate rug;
+use rug::Float;
+
+pub mod animate;
pub mod colour;
pub mod draw;
pub mod dump;
pub mod handle_keys;
pub mod initialise;
+pub mod r#loop;
pub mod poll_events;
pub mod render_row;
pub mod render;
@@ -42,17 +45,20 @@ pub struct Application {
canvas_width: u32,
canvas_height: u32,
scale: u32,
+ frame_count: u32,
- position_x: f64,
- position_y: f64,
- zoom: f64,
+ center_real: Float,
+ center_imaginary: Float,
+ zoom: Float,
maximum_iteration_count: u32,
dump_path: String,
- sdl: Sdl,
- sdl_video: VideoSubsystem,
- canvas: WindowCanvas,
+ video: Option<Video>,
+
+ interactive: bool,
+ do_draw: bool,
+ do_dump: bool,
- do_draw: bool,
+ precision: u32,
}
diff --git a/source/benoit/benoit/application/animate.rs b/source/benoit/benoit/application/animate.rs
new file mode 100644
index 0000000..6ff628e
--- /dev/null
+++ b/source/benoit/benoit/application/animate.rs
@@ -0,0 +1,85 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+use crate::benoit::application::Application;
+
+extern crate rug;
+extern crate sdl2;
+
+use rug::Float;
+use rug::ops::PowAssign;
+use std::ops::MulAssign;
+
+impl Application {
+ pub fn animate(&self) -> i32 {
+ let stop_zoom = Float::with_val(self.precision, &self.zoom);
+
+ let zoom_factor = {
+ // To get the zoom factor, we first want the 'a'
+ // value of the growth function from (0) and to
+ // (frame_count) on the x-dimension and from (1) to
+ // (zoom) on the y-dimension:
+ //
+ // a = nroot(x1-x0, y1/y0)
+ //
+ // but this may be simplified for use with Rug
+ // because
+ //
+ // nroot(a, b) = b^(1/a)
+ //
+ // making the final equation
+ //
+ // (x1-x0)^(1/y1*y0) = (zoom)^(1/frame_count)
+
+ let x_difference = Float::with_val(self.precision, self.frame_count);
+
+ let exponent = Float::with_val(self.precision, 1.0 / &x_difference);
+
+ let mut factor = Float::with_val(self.precision, &stop_zoom);
+ factor.pow_assign(exponent);
+
+ factor
+ };
+
+ let mut zoom = Float::with_val(self.precision, 1.0);
+
+ eprintln!("animating {} frames at {}{:+} to {:.3} (fac.: {:.3})", self.frame_count, self.center_real.to_f64(), self.center_imaginary.to_f64(), stop_zoom.to_f64(), zoom_factor.to_f64());
+
+ let canvas_size = self.canvas_height as usize * self.canvas_width as usize;
+
+ let mut data: Vec::<u32> = vec![0x0; canvas_size];
+ let mut image: Vec::<u8> = vec![0x0; canvas_size * 0x3];
+
+ for frame in 0x0..self.frame_count {
+ eprint!("{frame:010}: ");
+ self.render(&mut data[..], self.precision, &self.center_real, &self.center_imaginary, &zoom, self.maximum_iteration_count);
+ self.colour(&mut image[..], &data[..]);
+
+ self.dump(format!("{}/frame{frame:010}.webp", self.dump_path), &image, self.canvas_width, self.canvas_height);
+
+ zoom.mul_assign(&zoom_factor);
+ }
+
+ return 0x0;
+ }
+}
diff --git a/source/benoit/benoit/application/colour.rs b/source/benoit/benoit/application/colour.rs
index f0b1f19..db7e467 100644
--- a/source/benoit/benoit/application/colour.rs
+++ b/source/benoit/benoit/application/colour.rs
@@ -24,7 +24,7 @@
use crate::benoit::application::Application;
impl Application {
- pub fn colour(&mut self, buffer: &mut [u8], data: &[u32]) {
+ pub fn colour(&self, buffer: &mut [u8], data: &[u32]) {
let canvas_size = self.canvas_height * self.canvas_width;
for pixel in 0x0..canvas_size {
diff --git a/source/benoit/benoit/application/draw.rs b/source/benoit/benoit/application/draw.rs
index 6cf9196..c41d9c9 100644
--- a/source/benoit/benoit/application/draw.rs
+++ b/source/benoit/benoit/application/draw.rs
@@ -29,13 +29,10 @@ use sdl2::pixels::Color;
use sdl2::rect::Rect;
impl Application {
- pub fn draw(&mut self) {
+ pub fn draw(&mut self, data: &mut [u32], image: &mut [u8]) {
let canvas_size = self.canvas_height * self.canvas_width;
- let mut data: Vec::<u32> = vec![0x0; canvas_size as usize];
- self.render(&mut data[..], self.position_x, self.position_y, self.zoom, self.maximum_iteration_count);
-
- let mut image: Vec::<u8> = vec![0x0; canvas_size as usize * 0x3];
+ self.render(&mut data[..], self.precision, &self.center_real, &self.center_imaginary, &self.zoom, self.maximum_iteration_count);
self.colour(&mut image[..], &data[..]);
for pixel in 0x0..canvas_size {
@@ -45,7 +42,7 @@ impl Application {
let value = image[pixel as usize * 0x3];
let colour = Color::RGB(value, value, value);
- self.canvas.set_draw_color(colour);
+ self.video.as_mut().unwrap().canvas.set_draw_color(colour);
let rectangle = Rect::new(
(x * self.scale) as i32,
@@ -53,9 +50,9 @@ impl Application {
self.scale,
self.scale
);
- self.canvas.fill_rects(&[rectangle]).unwrap();
+ self.video.as_mut().unwrap().canvas.fill_rects(&[rectangle]).unwrap();
}
- self.canvas.present();
+ self.video.as_mut().unwrap().canvas.present();
}
}
diff --git a/source/benoit/benoit/application/dump.rs b/source/benoit/benoit/application/dump.rs
index ca658b3..a7b2915 100644
--- a/source/benoit/benoit/application/dump.rs
+++ b/source/benoit/benoit/application/dump.rs
@@ -29,16 +29,8 @@ use std::fs::write;
use webp::Encoder;
impl Application {
- pub fn dump(&mut self, path: String) {
- let canvas_size = self.canvas_height * self.canvas_width;
-
- let mut data: Vec::<u32> = vec![0x0; canvas_size as usize];
- self.render(&mut data[..], self.position_x, self.position_y, self.zoom, self.maximum_iteration_count);
-
- let mut image: Vec::<u8> = vec![0x0; canvas_size as usize * 0x3];
- self.colour(&mut image[..], &data[..]);
-
- let encoder = Encoder::from_rgb(&image[..], self.canvas_width, self.canvas_height);
+ pub fn dump(&self, path: String, image: &[u8], canvas_width: u32, canvas_height: u32) {
+ let encoder = Encoder::from_rgb(&image[..], canvas_width, canvas_height);
let data = encoder.encode_lossless();
diff --git a/source/benoit/benoit/application/handle_keys.rs b/source/benoit/benoit/application/handle_keys.rs
index 547971f..265bc18 100644
--- a/source/benoit/benoit/application/handle_keys.rs
+++ b/source/benoit/benoit/application/handle_keys.rs
@@ -23,36 +23,47 @@
use crate::benoit::application::Application;
+extern crate rug;
extern crate sdl2;
+use rug::Float;
use sdl2::keyboard::Scancode;
+use std::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
impl Application {
pub fn handle_keys(&mut self, scan_code: Scancode) -> bool {
match scan_code {
Scancode::Escape => return true,
- Scancode::X => self.dump(self.dump_path.clone()),
+ Scancode::C => self.do_draw = true,
+ Scancode::X => self.do_dump = true,
+ Scancode::Z => eprintln!("{}{:+}i -- {}x @ {} iter.", self.center_real, self.center_imaginary, self.zoom, self.maximum_iteration_count),
_ => {},
}
- self.zoom = match scan_code {
- Scancode::E => self.zoom * 4.0,
- Scancode::Q => self.zoom / 4.0,
- _ => self.zoom,
+ match scan_code {
+ Scancode::E => self.zoom.mul_assign(4.0),
+ Scancode::Q => self.zoom.div_assign(4.0),
+ _ => {},
};
- let translate_ammount: f64 = 1.0 / 4.0 / self.zoom;
+ let translate_ammount = {
+ let mut ammount = Float::with_val(self.precision, 1.0);
+ ammount.div_assign(4.0);
+ ammount.div_assign(&self.zoom);
- self.position_x += match scan_code {
- Scancode::A => -translate_ammount,
- Scancode::D => translate_ammount,
- _ => 0.0,
+ ammount
};
- self.position_y += match scan_code {
- Scancode::S => translate_ammount,
- Scancode::W => -translate_ammount,
- _ => 0.0,
+ match scan_code {
+ Scancode::A => self.center_real.sub_assign(&translate_ammount),
+ Scancode::D => self.center_real.add_assign(&translate_ammount),
+ _ => {},
+ };
+
+ match scan_code {
+ Scancode::S => self.center_imaginary.add_assign(&translate_ammount),
+ Scancode::W => self.center_imaginary.sub_assign(&translate_ammount),
+ _ => {},
};
self.maximum_iteration_count = match scan_code {
@@ -61,18 +72,6 @@ impl Application {
_ => self.maximum_iteration_count,
};
- self.do_draw = match scan_code {
- Scancode::A => true,
- Scancode::D => true,
- Scancode::E => true,
- Scancode::F => true,
- Scancode::Q => true,
- Scancode::R => true,
- Scancode::S => true,
- Scancode::W => true,
- _ => false,
- };
-
return false;
}
}
diff --git a/source/benoit/benoit/application/initialise.rs b/source/benoit/benoit/application/initialise.rs
index 4e9386f..6091da2 100644
--- a/source/benoit/benoit/application/initialise.rs
+++ b/source/benoit/benoit/application/initialise.rs
@@ -23,8 +23,13 @@
use crate::benoit::application::Application;
use crate::benoit::configuration::Configuration;
+use crate::benoit::video::Video;
+extern crate rug;
+
+use rug::Float;
use std::env::args;
+use std::thread::available_parallelism;
impl Application {
pub fn initialise() -> Application {
@@ -35,32 +40,46 @@ impl Application {
None => Configuration::default(),
};
- let sdl = sdl2::init().expect("unable to initialise sdl2");
- let sdl_video = sdl.video().expect("unable to initialise video");
+ let precision: u32 = 0x100;
- let window = sdl_video.window("Benoit", configuration.canvas_width * configuration.scale, configuration.canvas_height * configuration.scale).position_centered().build().expect("unable to open window");
+ let thread_count: u32 = if configuration.thread_count == 0x0 {
+ match available_parallelism() {
+ Ok(ammount) => ammount.get() as u32,
+ _ => 0x2,
+ }
+ } else {
+ configuration.thread_count
+ };
- let canvas = window.into_canvas().build().expect("unable to create canvas");
+ eprintln!("using {thread_count} threads");
+
+ let video = match configuration.interactive {
+ true => Some(Video::initialise(configuration.canvas_width, configuration.canvas_height, configuration.scale)),
+ false => None,
+ };
return Application {
- thread_count: configuration.thread_count,
+ thread_count: thread_count,
canvas_width: configuration.canvas_width,
canvas_height: configuration.canvas_height,
scale: configuration.scale,
+ frame_count: configuration.frame_count,
- position_x: configuration.position_x,
- position_y: configuration.position_y,
- zoom: configuration.zoom,
+ center_real: Float::with_val(precision, configuration.center_real),
+ center_imaginary: Float::with_val(precision, configuration.center_imaginary),
+ zoom: Float::with_val(precision, configuration.zoom),
maximum_iteration_count: configuration.maximum_iteration_count,
dump_path: configuration.dump_path,
- sdl: sdl,
- sdl_video: sdl_video,
- canvas: canvas,
+ video: video,
+
+ interactive: configuration.interactive,
+ do_draw: true,
+ do_dump: false,
- do_draw: true,
+ precision: precision,
};
}
}
diff --git a/source/benoit/benoit/application/loop.rs b/source/benoit/benoit/application/loop.rs
new file mode 100644
index 0000000..dd35c63
--- /dev/null
+++ b/source/benoit/benoit/application/loop.rs
@@ -0,0 +1,76 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+use crate::benoit::application::Application;
+
+extern crate sdl2;
+
+impl Application {
+ pub fn r#loop(&mut self) -> i32 {
+ eprintln!();
+ eprintln!("Controls:");
+ eprintln!("- W Translate up");
+ eprintln!("- A Translate left");
+ eprintln!("- S Translate down");
+ eprintln!("- D Translate right");
+ eprintln!();
+ eprintln!("- Q Zoom out");
+ eprintln!("- E Zoom in");
+ eprintln!();
+ eprintln!("- R Decrease max. iteration count");
+ eprintln!("- F Increase max. iteration count");
+ eprintln!();
+ eprintln!("- Z Print center value (c)");
+ eprintln!("- X Dump render");
+ eprintln!("- C Render frame");
+ eprintln!();
+
+ let mut event_pump = self.video.as_mut().unwrap().sdl.event_pump().expect("unable to get event pump");
+
+ let canvas_size = self.canvas_height as usize * self.canvas_width as usize;
+
+ let mut data: Vec::<u32> = vec![0x0; canvas_size];
+ let mut image: Vec::<u8> = vec![0x0; canvas_size * 0x3];
+
+ loop {
+ if self.poll_events(&mut event_pump) { break }
+
+ if self.do_draw {
+ self.draw(data.as_mut_slice(), image.as_mut_slice());
+
+ self.do_draw = false;
+ }
+
+ if self.do_dump {
+ let path = format!("{}/image.webp", self.dump_path);
+
+ eprintln!("dumping image at \"{path}\"");
+ self.dump(path, &image, self.canvas_width, self.canvas_height);
+
+ self.do_dump = false;
+ }
+ }
+
+ return 0x0;
+ }
+}
diff --git a/source/benoit/benoit/application/render.rs b/source/benoit/benoit/application/render.rs
index df14024..e353732 100644
--- a/source/benoit/benoit/application/render.rs
+++ b/source/benoit/benoit/application/render.rs
@@ -23,20 +23,25 @@
use crate::benoit::application::Application;
+extern crate rug;
+
+use rug::Float;
use std::slice;
use std::thread::{JoinHandle, spawn};
use std::time::Instant;
use std::ptr::addr_of_mut;
impl Application {
- pub fn render(&mut self, buffer: &mut [u32], position_x: f64, position_y: f64, zoom: f64, maximum_iteration_count: u32) {
- eprintln!("rendering: {}{:+}i ({}x) @ ({})", position_x, position_y, zoom, maximum_iteration_count);
+ pub fn render(&self, buffer: &mut [u32], precision: u32, center_real: &Float, center_imaginary: &Float, zoom: &Float, maximum_iteration_count: u32) {
+ eprint!("rendering...");
let mut threads = Vec::<JoinHandle<()>>::with_capacity(self.thread_count as usize);
let time_start = Instant::now();
'render_loop: {
+ // We render the set using one thread per row.
+
let get_slice = |buffer: &mut [u32], y: u32, canvas_width: u32| -> &mut [u32] {
let slice_start = y as usize * canvas_width as usize;
let slice = unsafe { slice::from_raw_parts_mut(addr_of_mut!(buffer[slice_start]), canvas_width as usize) };
@@ -46,34 +51,46 @@ impl Application {
let canvas_width = self.canvas_width;
let canvas_height = self.canvas_height;
- let position_x = position_x;
- let position_y = position_y;
- let zoom = zoom;
- let maximum_iteration_count = maximum_iteration_count;
- let mut y: u32 = 0x0;
+ // Firstly, we fill up the thread vector by
+ // spawning threads.
+ let mut y: u32 = 0x0;
for _thread in 0x0..self.thread_count {
+ // We should stop if there are no remaining rows.
if y == self.canvas_height { break 'render_loop; }
let buffer_slice = get_slice(buffer, y, self.canvas_width);
- threads.push(spawn(move || { Application::render_row(buffer_slice, y, canvas_width, canvas_height, position_x, position_y, zoom, maximum_iteration_count) }));
+ let center_real = center_real.clone();
+ let center_imaginary = center_imaginary.clone();
+ let zoom = zoom.clone();
+
+ threads.push(spawn(move || { Application::render_row(buffer_slice, precision, y, canvas_width, canvas_height, center_real, center_imaginary, zoom, maximum_iteration_count) }));
y += 0x1;
}
+ // Secondly, we continuously join the first thread
+ // to spawn another one. This is as to make the
+ // threads more "active" by making the take on more
+ // rows when they complete.
+
for y in 0x0..self.canvas_height {
threads.remove(0x0).join().unwrap();
let buffer_slice = get_slice(buffer, y, self.canvas_width);
- threads.push(spawn(move || { Application::render_row(buffer_slice, y, canvas_width, canvas_height, position_x, position_y, zoom, maximum_iteration_count) }));
+ let center_real = center_real.clone();
+ let center_imaginary = center_imaginary.clone();
+ let zoom = zoom.clone();
+
+ threads.push(spawn(move || { Application::render_row(buffer_slice, precision, y, canvas_width, canvas_height, center_real, center_imaginary, zoom, maximum_iteration_count) }));
}
}
let duration = time_start.elapsed();
- eprintln!("done ({}ms)", duration.as_millis());
+ eprintln!(" done ({}ms)", duration.as_millis());
}
}
diff --git a/source/benoit/benoit/application/render_row.rs b/source/benoit/benoit/application/render_row.rs
index 80e3646..64f9f4c 100644
--- a/source/benoit/benoit/application/render_row.rs
+++ b/source/benoit/benoit/application/render_row.rs
@@ -23,22 +23,60 @@
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, position_x: f64, position_y: f64, zoom: f64, maximum_iteration_count: u32) {
+ pub fn render_row(data: &mut [u32], precision: 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 = canvas_width as f64;
- let canvas_height = canvas_height as f64;
+ 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 + &center_real);
+ //let cb = Float::with_val(precision, (&y - &canvas_height / 2.0) / &canvas_height * 4.0 / &zoom + &center_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 ca = (x as f64 - canvas_width / 2.0) / canvas_width * 4.0 / zoom + position_x;
- let cb = (y as f64 - canvas_height / 2.0) / canvas_height * 4.0 / zoom + position_y;
+ 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(&center_real);
- let mut za: f64 = 0.0;
- let mut zb: f64 = 0.0;
+ 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(&center_imaginary);
+
+ cb
+ };
+
+ 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 {
- let square_distance = za * za + zb * zb;
- if square_distance > 2.0 * 2.0 { break }
+ let square_distance = Float::with_val(precision, &za * &za + &zb * &zb);
+ if square_distance > 4.0 { break }
{
// z = z^2 + c
@@ -47,15 +85,19 @@ impl Application {
// a = a^2 - b^2
// b = 2abi
- let za_temporary = za;
- za = za * za - zb * zb + ca;
- zb = za_temporary * zb * 2.0 + cb;
+ let za_temporary = Float::with_val(precision, &za);
+
+ za = Float::with_val(precision, &za * &za - &zb * &zb);
+ za = Float::with_val(precision, &za + &ca);
+
+ zb = Float::with_val(precision, &za_temporary * &zb);
+ zb = Float::with_val(precision, &zb * &two + &cb);
}
iteration_count += 0x1;
}
- data[x as usize] = iteration_count;
+ unsafe { *data.get_unchecked_mut(x as usize) = iteration_count }
}
}
}
diff --git a/source/benoit/benoit/application/run.rs b/source/benoit/benoit/application/run.rs
index 393918a..d764084 100644
--- a/source/benoit/benoit/application/run.rs
+++ b/source/benoit/benoit/application/run.rs
@@ -26,17 +26,10 @@ use crate::benoit::application::Application;
extern crate sdl2;
impl Application {
- pub fn run(&mut self) {
- let mut event_pump = self.sdl.event_pump().expect("unable to get event pump");
-
- loop {
- if self.poll_events(&mut event_pump) { break }
-
- if self.do_draw {
- self.draw();
-
- self.do_draw = false;
- }
- }
+ pub fn run(&mut self) -> i32 {
+ return match self.interactive {
+ true => self.r#loop(),
+ false => self.animate(),
+ };
}
}
diff --git a/source/benoit/benoit/configuration.rs b/source/benoit/benoit/configuration.rs
index 6783f21..29a2b67 100644
--- a/source/benoit/benoit/configuration.rs
+++ b/source/benoit/benoit/configuration.rs
@@ -30,11 +30,14 @@ pub struct Configuration {
pub canvas_width: u32,
pub canvas_height: u32,
pub scale: u32,
+ pub frame_count: u32,
- pub position_x: f64,
- pub position_y: f64,
+ pub center_real: f64,
+ pub center_imaginary: f64,
pub zoom: f64,
pub maximum_iteration_count: u32,
pub dump_path: String,
+
+ pub interactive: bool,
}
diff --git a/source/benoit/benoit/configuration/default.rs b/source/benoit/benoit/configuration/default.rs
index ddc6578..227e588 100644
--- a/source/benoit/benoit/configuration/default.rs
+++ b/source/benoit/benoit/configuration/default.rs
@@ -26,18 +26,21 @@ use crate::benoit::configuration::Configuration;
impl Configuration {
pub fn default() -> Configuration {
return Configuration {
- thread_count: 0x2,
+ thread_count: 0x0,
canvas_width: 0x100,
canvas_height: 0x100,
scale: 0x1,
+ frame_count: 0x10,
- position_x: 0.0,
- position_y: 0.0,
+ center_real: 0.0,
+ center_imaginary: 0.0,
zoom: 1.0,
maximum_iteration_count: 0x100,
- dump_path: "./image.webp".to_string(),
+ dump_path: "./render/".to_string(),
+
+ interactive: true,
};
}
}
diff --git a/source/benoit/benoit/configuration/load.rs b/source/benoit/benoit/configuration/load.rs
index 1c0cfe8..cf74548 100644
--- a/source/benoit/benoit/configuration/load.rs
+++ b/source/benoit/benoit/configuration/load.rs
@@ -35,6 +35,8 @@ impl Configuration {
let mut configuration = Configuration::default();
+ configuration.interactive = false;
+
let configuration_text = match read(path) {
Ok(content) => String::from_utf8_lossy(&content).to_string(),
Err(..) => {
@@ -68,11 +70,11 @@ impl Configuration {
get_integer(&mut configuration.canvas_width, &configuration_table, "canvas_width");
get_integer(&mut configuration.canvas_height, &configuration_table, "canvas_height");
get_integer(&mut configuration.scale, &configuration_table, "scale");
+ get_integer(&mut configuration.frame_count, &configuration_table, "frame_count");
- get_float(&mut configuration.position_x, &configuration_table, "real");
- get_float(&mut configuration.position_y, &configuration_table, "imaginary");
- get_float(&mut configuration.zoom, &configuration_table, "zoom");
-
+ get_float( &mut configuration.center_real, &configuration_table, "real");
+ get_float( &mut configuration.center_imaginary, &configuration_table, "imaginary");
+ get_float( &mut configuration.zoom, &configuration_table, "zoom");
get_integer(&mut configuration.maximum_iteration_count, &configuration_table, "maximum_iteration_count");
return configuration;
diff --git a/source/benoit/benoit/video.rs b/source/benoit/benoit/video.rs
new file mode 100644
index 0000000..2147b27
--- /dev/null
+++ b/source/benoit/benoit/video.rs
@@ -0,0 +1,34 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+extern crate sdl2;
+
+use sdl2::Sdl;
+use sdl2::render::WindowCanvas;
+
+pub mod initialise;
+
+pub struct Video {
+ pub sdl: Sdl,
+ pub canvas: WindowCanvas,
+}
diff --git a/source/benoit/benoit/video/initialise.rs b/source/benoit/benoit/video/initialise.rs
new file mode 100644
index 0000000..595140d
--- /dev/null
+++ b/source/benoit/benoit/video/initialise.rs
@@ -0,0 +1,42 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+use crate::benoit::video::Video;
+
+extern crate sdl2;
+
+impl Video {
+ pub fn initialise(canvas_width: u32, canvas_height: 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_height * scale).position_centered().build().expect("unable to open window");
+
+ let canvas = window.into_canvas().build().expect("unable to create canvas");
+
+ return Video {
+ sdl: sdl,
+ canvas: canvas,
+ };
+ }
+}
diff --git a/source/benoit/main.rs b/source/benoit/main.rs
index bffc05d..a302b9f 100644
--- a/source/benoit/main.rs
+++ b/source/benoit/main.rs
@@ -25,7 +25,14 @@ mod benoit;
use benoit::application::Application;
+use std::mem::drop;
+use std::process::exit;
+
fn main() {
let mut application = Application::initialise();
- application.run();
+ let code = application.run();
+
+ drop(application);
+
+ exit(code);
}