summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md6
-rw-r--r--Cargo.toml2
-rw-r--r--source/benoit/benoit/application.rs22
-rw-r--r--source/benoit/benoit/application/animate.rs4
-rw-r--r--source/benoit/benoit/application/draw.rs11
-rw-r--r--source/benoit/benoit/application/get_row_renderer.rs34
-rw-r--r--source/benoit/benoit/application/handle_keys.rs38
-rw-r--r--source/benoit/benoit/application/initialise.rs8
-rw-r--r--source/benoit/benoit/application/loop.rs25
-rw-r--r--source/benoit/benoit/application/render.rs9
-rw-r--r--source/benoit/benoit/application/render_row_julia.rs92
-rw-r--r--source/benoit/benoit/application/render_row_normal.rs (renamed from source/benoit/benoit/application/render_row.rs)2
-rw-r--r--source/benoit/benoit/configuration.rs5
-rw-r--r--source/benoit/benoit/configuration/default.rs7
-rw-r--r--source/benoit/benoit/configuration/load.rs6
15 files changed, 226 insertions, 45 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5e503d8..f7cd193 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+# 27
+
+* Bring back Julia sets (using row renderers)
+* Update controls (decrease sensitivity of zooms)
+* Scale by default
+
# 26
* Update colouring for small iteration counts
diff --git a/Cargo.toml b/Cargo.toml
index c6ccb63..942e27b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "benoit"
-version = "0.30.0"
+version = "0.31.0"
authors = ["Gabriel Bjørnager Jensen"]
edition = "2021"
description = "Mandelbrot renderer."
diff --git a/source/benoit/benoit/application.rs b/source/benoit/benoit/application.rs
index be3d0fb..1830721 100644
--- a/source/benoit/benoit/application.rs
+++ b/source/benoit/benoit/application.rs
@@ -23,37 +23,50 @@
use crate::benoit::fractal::Fractal;
use crate::benoit::iteration::IteratorFunction;
+use crate::benoit::render_data::RenderData;
use crate::benoit::video::Video;
extern crate rug;
use rug::Float;
+use std::sync::Arc;
pub mod animate;
pub mod colour;
pub mod draw;
pub mod dump;
pub mod get_iterator_function;
+pub mod get_row_renderer;
pub mod handle_keys;
pub mod initialise;
pub mod r#loop;
pub mod poll_events;
-pub mod render_row;
+pub mod render_row_julia;
+pub mod render_row_normal;
pub mod render;
pub mod run;
+pub type RowRenderer = fn(Arc<RenderData>, u32, IteratorFunction);
+
+pub struct PreviousPosition {
+ real: Float,
+ imaginary: Float,
+ zoom: Float,
+}
+
pub struct Application {
thread_count: u32,
fractal: Fractal,
+ julia: bool,
canvas_width: u32,
canvas_height: u32,
scale: u32,
frame_count: u32,
- center_real: Float,
- center_imaginary: Float,
+ centre_real: Float,
+ centre_imaginary: Float,
zoom: Float,
maximum_iteration_count: u32,
@@ -62,8 +75,9 @@ pub struct Application {
video: Option<Video>,
interactive: bool,
- do_draw: bool,
+ do_render: bool,
do_dump: bool,
+ row_renderer: RowRenderer,
iterator_function: IteratorFunction,
}
diff --git a/source/benoit/benoit/application/animate.rs b/source/benoit/benoit/application/animate.rs
index 48677f3..3c9aaab 100644
--- a/source/benoit/benoit/application/animate.rs
+++ b/source/benoit/benoit/application/animate.rs
@@ -66,7 +66,7 @@ impl Application {
factor
};
- eprintln!("animating {} frames at {}{:+}i to {:.3} (fac.: {:.3})", self.frame_count, self.center_real.to_f64(), self.center_imaginary.to_f64(), zoom_stop.to_f64(), zoom_factor.to_f64());
+ eprintln!("animating {} frames at {}{:+}i to {:.3} (fac.: {:.3})", self.frame_count, self.centre_real.to_f64(), self.centre_imaginary.to_f64(), zoom_stop.to_f64(), zoom_factor.to_f64());
let canvas_size = self.canvas_height as usize * self.canvas_width as usize;
@@ -77,7 +77,7 @@ impl Application {
for frame in 0x0..self.frame_count {
eprint!("{frame:010}: ");
- self.render(&mut iteration_count_buffer[..], &mut square_distance_buffer[..], &self.center_real, &self.center_imaginary, &zoom, self.maximum_iteration_count);
+ self.render(&mut iteration_count_buffer[..], &mut square_distance_buffer[..], &self.centre_real, &self.centre_imaginary, &zoom, self.maximum_iteration_count);
self.colour(&mut image[..], &mut iteration_count_buffer[..], &mut square_distance_buffer[..]);
self.dump(format!("{}/frame{frame:010}.webp", self.dump_path), &image, self.canvas_width, self.canvas_height);
diff --git a/source/benoit/benoit/application/draw.rs b/source/benoit/benoit/application/draw.rs
index 6b1300b..ae936ba 100644
--- a/source/benoit/benoit/application/draw.rs
+++ b/source/benoit/benoit/application/draw.rs
@@ -21,15 +21,18 @@
If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::benoit::application::Application;
+use crate::benoit::PRECISION;
+use crate::benoit::application::{Application, PreviousPosition};
+extern crate rug;
extern crate sdl2;
+use rug::Float;
use sdl2::pixels::Color;
use sdl2::rect::Rect;
impl Application {
- pub fn draw(&mut self, image: &[u8]) {
+ pub fn draw(&mut self, image: &[u8], previous_position: &PreviousPosition) {
let canvas_size = self.canvas_height * self.canvas_width;
for pixel in 0x0..canvas_size {
@@ -44,14 +47,14 @@ impl Application {
Color::RGB(red, green, blue)
};
- self.video.as_mut().unwrap().canvas.set_draw_color(colour);
-
let rectangle = Rect::new(
(x * self.scale) as i32,
(y * self.scale) as i32,
self.scale,
self.scale
);
+
+ self.video.as_mut().unwrap().canvas.set_draw_color(colour);
self.video.as_mut().unwrap().canvas.fill_rects(&[rectangle]).unwrap();
}
diff --git a/source/benoit/benoit/application/get_row_renderer.rs b/source/benoit/benoit/application/get_row_renderer.rs
new file mode 100644
index 0000000..d8c349a
--- /dev/null
+++ b/source/benoit/benoit/application/get_row_renderer.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/>.
+*/
+
+use crate::benoit::application::Application;
+use crate::benoit::application::RowRenderer;
+
+impl Application {
+ pub fn get_row_renderer(julia: bool) -> RowRenderer {
+ return match julia {
+ false => Application::render_row_normal,
+ true => Application::render_row_julia,
+ };
+ }
+}
diff --git a/source/benoit/benoit/application/handle_keys.rs b/source/benoit/benoit/application/handle_keys.rs
index 659a584..4b2c09c 100644
--- a/source/benoit/benoit/application/handle_keys.rs
+++ b/source/benoit/benoit/application/handle_keys.rs
@@ -22,7 +22,7 @@
*/
use crate::benoit::PRECISION;
-use crate::benoit::application::Application;
+use crate::benoit::application::{Application, RowRenderer};
use crate::benoit::fractal::Fractal;
use crate::benoit::iteration::IteratorFunction;
@@ -46,40 +46,54 @@ fn cycle_fractal(fractal: Fractal) -> (Fractal, IteratorFunction) {
return (fractal, iterator_function);
}
+fn toggle_julia(julia: bool) -> (bool, RowRenderer) {
+ let julia = !julia;
+
+ let row_renderer = Application::get_row_renderer(julia);
+
+ match julia {
+ false => eprintln!("enabled the julia set"),
+ true => eprintln!("disabled the julia set"),
+ };
+
+ return (julia, row_renderer);
+}
+
impl Application {
pub fn handle_keys(&mut self, scan_code: Scancode) -> bool {
match scan_code {
+ Scancode::LAlt => (self.fractal, self.iterator_function) = cycle_fractal(self.fractal),
Scancode::Escape => return true,
- Scancode::C => self.do_draw = true,
- Scancode::Tab => (self.fractal, self.iterator_function) = cycle_fractal(self.fractal),
+ Scancode::C => self.do_render = true,
+ Scancode::Tab => (self.julia, self.row_renderer) = toggle_julia(self.julia),
Scancode::X => self.do_dump = true,
- Scancode::Z => eprintln!("c = {}{:+}i -- {}x @ {} iter.", &self.center_real, &self.center_imaginary, &self.zoom, self.maximum_iteration_count),
+ Scancode::Z => eprintln!("c = {}{:+}i -- {}x @ {} iter.", &self.centre_real, &self.centre_imaginary, &self.zoom, self.maximum_iteration_count),
_ => {},
}
match scan_code {
- Scancode::E => self.zoom *= 4.0,
- Scancode::Q => self.zoom /= 4.0,
+ Scancode::E => self.zoom *= 2.0,
+ Scancode::Q => self.zoom /= 2.0,
_ => {},
};
let translate_ammount = {
- let mut ammount = Float::with_val(PRECISION, 1.0);
- ammount /= 4.0;
+ let mut ammount = Float::with_val(PRECISION, 4.0);
+ ammount /= 16.0;
ammount /= &self.zoom;
ammount
};
match scan_code {
- Scancode::A => self.center_real -= &translate_ammount,
- Scancode::D => self.center_real += &translate_ammount,
+ Scancode::A => self.centre_real -= &translate_ammount,
+ Scancode::D => self.centre_real += &translate_ammount,
_ => {},
};
match scan_code {
- Scancode::S => self.center_imaginary += &translate_ammount,
- Scancode::W => self.center_imaginary -= &translate_ammount,
+ Scancode::S => self.centre_imaginary += &translate_ammount,
+ Scancode::W => self.centre_imaginary -= &translate_ammount,
_ => {},
};
diff --git a/source/benoit/benoit/application/initialise.rs b/source/benoit/benoit/application/initialise.rs
index 97ac4a4..e46347c 100644
--- a/source/benoit/benoit/application/initialise.rs
+++ b/source/benoit/benoit/application/initialise.rs
@@ -65,14 +65,15 @@ impl Application {
thread_count: thread_count,
fractal: configuration.fractal,
+ julia: configuration.julia,
canvas_width: configuration.canvas_width,
canvas_height: configuration.canvas_height,
scale: configuration.scale,
frame_count: configuration.frame_count,
- center_real: Float::with_val(PRECISION, configuration.center_real),
- center_imaginary: Float::with_val(PRECISION, configuration.center_imaginary),
+ centre_real: Float::with_val(PRECISION, configuration.centre_real),
+ centre_imaginary: Float::with_val(PRECISION, configuration.centre_imaginary),
zoom: Float::with_val(PRECISION, configuration.zoom),
maximum_iteration_count: configuration.maximum_iteration_count,
@@ -81,9 +82,10 @@ impl Application {
video: video,
interactive: configuration.interactive,
- do_draw: true,
+ do_render: true,
do_dump: false,
+ row_renderer: Application::get_row_renderer( configuration.julia),
iterator_function: Application::get_iterator_function(configuration.fractal),
};
}
diff --git a/source/benoit/benoit/application/loop.rs b/source/benoit/benoit/application/loop.rs
index f6747e7..2621556 100644
--- a/source/benoit/benoit/application/loop.rs
+++ b/source/benoit/benoit/application/loop.rs
@@ -21,7 +21,7 @@
If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::benoit::application::Application;
+use crate::benoit::application::{Application, PreviousPosition};
extern crate sdl2;
@@ -40,7 +40,8 @@ impl Application {
eprintln!("- R Decrease max. iteration count");
eprintln!("- F Increase max. iteration count");
eprintln!();
- eprintln!("- Tab Cycle between fractals");
+ eprintln!("- Tab Toggle Julia");
+ eprintln!("- Alt Cycle between fractals");
eprintln!();
eprintln!("- Z Print centre value (c)");
eprintln!("- X Dump frame");
@@ -56,18 +57,30 @@ impl Application {
let mut image: Vec::<u8> = vec![0x0; canvas_size * 0x3];
+ let mut previous_position = PreviousPosition {
+ real: self.centre_real.clone(),
+ imaginary: self.centre_imaginary.clone(),
+ zoom: self.zoom.clone(),
+ };
+
loop {
if self.poll_events(&mut event_pump) { break }
- if self.do_draw {
- self.render(&mut iteration_count_buffer[..], &mut square_distance_buffer[..], &self.center_real, &self.center_imaginary, &self.zoom, self.maximum_iteration_count);
+ if self.do_render {
+ self.render(&mut iteration_count_buffer[..], &mut square_distance_buffer[..], &self.centre_real, &self.centre_imaginary, &self.zoom, self.maximum_iteration_count);
self.colour(&mut image[..], &iteration_count_buffer[..], &square_distance_buffer[..]);
- self.draw(&image[..]);
+ previous_position = PreviousPosition {
+ real: self.centre_real.clone(),
+ imaginary: self.centre_imaginary.clone(),
+ zoom: self.zoom.clone(),
+ };
- self.do_draw = false;
+ self.do_render = false;
}
+ self.draw(&image[..], &previous_position);
+
if self.do_dump {
let path = format!("{}/image.webp", self.dump_path);
diff --git a/source/benoit/benoit/application/render.rs b/source/benoit/benoit/application/render.rs
index 17ccc88..3063d6f 100644
--- a/source/benoit/benoit/application/render.rs
+++ b/source/benoit/benoit/application/render.rs
@@ -33,17 +33,18 @@ use std::sync::Arc;
use std::time::Instant;
impl Application {
- pub fn render(&self, iteration_count_buffer: &mut [u32], square_distance_buffer: &mut [f32], center_real: &Float, center_imaginary: &Float, zoom: &Float, maximum_iteration_count: u32) {
+ pub fn render(&self, iteration_count_buffer: &mut [u32], square_distance_buffer: &mut [f32], centre_real: &Float, centre_imaginary: &Float, zoom: &Float, maximum_iteration_count: u32) {
eprint!("rendering...");
let time_start = Instant::now();
- let iterator = self.iterator_function;
+ let row_renderer = self.row_renderer;
+ let iterator = self.iterator_function;
- let data = Arc::new(RenderData::new(iteration_count_buffer, square_distance_buffer, self.canvas_width, self.canvas_height, center_real.clone(), center_imaginary.clone(), zoom.clone(), maximum_iteration_count));
+ let data = Arc::new(RenderData::new(iteration_count_buffer, square_distance_buffer, self.canvas_width, self.canvas_height, centre_real.clone(), centre_imaginary.clone(), zoom.clone(), maximum_iteration_count));
(0x0..self.canvas_height).into_par_iter().for_each(|row| {
- Application::render_row(data.clone(), row, iterator);
+ row_renderer(data.clone(), row, iterator);
});
let duration = time_start.elapsed();
diff --git a/source/benoit/benoit/application/render_row_julia.rs b/source/benoit/benoit/application/render_row_julia.rs
new file mode 100644
index 0000000..ba46afa
--- /dev/null
+++ b/source/benoit/benoit/application/render_row_julia.rs
@@ -0,0 +1,92 @@
+/*
+ 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::PRECISION;
+use crate::benoit::application::Application;
+use crate::benoit::iteration::IteratorFunction;
+use crate::benoit::render_data::RenderData;
+
+extern crate rug;
+
+use rug::Float;
+use std::sync::Arc;
+
+impl Application {
+ pub fn render_row_julia(data: Arc<RenderData>, y: u32, iterator: IteratorFunction) {
+ let (iteration_count_buffer, square_distance_buffer) = unsafe { data.slice(y) };
+
+ for x in 0x0..data.canvas_width {
+ let canvas_width = Float::with_val(PRECISION, data.canvas_width);
+ let canvas_height = Float::with_val(PRECISION, data.canvas_height);
+
+ let x_float = Float::with_val(PRECISION, x);
+ let y_float = Float::with_val(PRECISION, y);
+
+ // For more information, see render_row_normal.
+
+ let ca = &data.real;
+ let cb = &data.imaginary;
+
+ // When rendering the Julia fractals, the value of
+ // (c) remains constant throughout the entire
+ // canvas. The value of (z) - however - takes the
+ // position-determined value that (c) would've had.
+
+ let mut za = {
+ let tmp0 = Float::with_val(PRECISION, &canvas_width / 2.0);
+
+ let mut za = Float::with_val(PRECISION, &x_float - &tmp0);
+ za *= 4.0;
+ za /= &canvas_width;
+
+ za
+ };
+
+ let mut zb = {
+ let tmp0 = Float::with_val(PRECISION, &canvas_height / 2.0);
+
+ let mut zb = Float::with_val(PRECISION, &y_float - &tmp0);
+ zb *= 4.0;
+ zb /= &canvas_height;
+
+ zb
+ };
+
+ let mut iteration_count: u32 = 0x0;
+ let mut square_distance;
+ while {
+ square_distance = Float::with_val(PRECISION, &za * &za + &zb * &zb).to_f32();
+ square_distance <= 256.0 && iteration_count < data.maximum_iteration_count
+ } {
+ iterator(&mut za, &mut zb, ca, cb);
+
+ iteration_count += 0x1;
+ }
+
+ unsafe {
+ *iteration_count_buffer.get_unchecked_mut(x as usize) = iteration_count;
+ *square_distance_buffer.get_unchecked_mut(x as usize) = square_distance;
+ }
+ }
+ }
+}
diff --git a/source/benoit/benoit/application/render_row.rs b/source/benoit/benoit/application/render_row_normal.rs
index 23946ec..570f9d4 100644
--- a/source/benoit/benoit/application/render_row.rs
+++ b/source/benoit/benoit/application/render_row_normal.rs
@@ -32,7 +32,7 @@ use rug::Float;
use std::sync::Arc;
impl Application {
- pub fn render_row(data: Arc<RenderData>, y: u32, iterator: IteratorFunction) {
+ pub fn render_row_normal(data: Arc<RenderData>, y: u32, iterator: IteratorFunction) {
let (iteration_count_buffer, square_distance_buffer) = unsafe { data.slice(y) };
for x in 0x0..data.canvas_width {
diff --git a/source/benoit/benoit/configuration.rs b/source/benoit/benoit/configuration.rs
index 455107f..730835a 100644
--- a/source/benoit/benoit/configuration.rs
+++ b/source/benoit/benoit/configuration.rs
@@ -34,14 +34,15 @@ pub struct Configuration {
pub thread_count: u32,
pub fractal: Fractal,
+ pub julia: bool,
pub canvas_width: u32,
pub canvas_height: u32,
pub scale: u32,
pub frame_count: u32,
- pub center_real: Float,
- pub center_imaginary: Float,
+ pub centre_real: Float,
+ pub centre_imaginary: Float,
pub zoom: Float,
pub maximum_iteration_count: u32,
diff --git a/source/benoit/benoit/configuration/default.rs b/source/benoit/benoit/configuration/default.rs
index b8649b5..c992951 100644
--- a/source/benoit/benoit/configuration/default.rs
+++ b/source/benoit/benoit/configuration/default.rs
@@ -35,14 +35,15 @@ impl Configuration {
thread_count: 0x0,
fractal: Fractal::Mandelbrot,
+ julia: false,
canvas_width: 0x100,
canvas_height: 0x100,
- scale: 0x1,
+ scale: 0x2,
frame_count: 0x10,
- center_real: Float::with_val(PRECISION, 0.0),
- center_imaginary: Float::with_val(PRECISION, 0.0),
+ centre_real: Float::with_val(PRECISION, 0.0),
+ centre_imaginary: Float::with_val(PRECISION, 0.0),
zoom: Float::with_val(PRECISION, 1.0),
maximum_iteration_count: 0x100,
diff --git a/source/benoit/benoit/configuration/load.rs b/source/benoit/benoit/configuration/load.rs
index 4f5f557..a4ac83c 100644
--- a/source/benoit/benoit/configuration/load.rs
+++ b/source/benoit/benoit/configuration/load.rs
@@ -83,7 +83,7 @@ impl Configuration {
};
};
- get_integer(&mut configuration.thread_count, &configuration_table, "thread_count");
+ get_integer(&mut configuration.thread_count, &configuration_table, "thread_count");
configuration.fractal = if let Some(name) = get_string(&configuration_table, "fractal") {
match name.as_str() {
@@ -101,8 +101,8 @@ impl Configuration {
get_integer(&mut configuration.scale, &configuration_table, "scale");
get_integer(&mut configuration.frame_count, &configuration_table, "frame_count");
- get_float( &mut configuration.center_real, &configuration_table, "real");
- get_float( &mut configuration.center_imaginary, &configuration_table, "imaginary");
+ get_float( &mut configuration.centre_real, &configuration_table, "real");
+ get_float( &mut configuration.centre_imaginary, &configuration_table, "imaginary");
get_float( &mut configuration.zoom, &configuration_table, "zoom");
get_integer(&mut configuration.maximum_iteration_count, &configuration_table, "maximum_iteration_count");