fix: refactor parts of mandelbrot.rs
This commit is contained in:
parent
42c783448e
commit
3d0f2acea3
|
@ -1,2 +1,3 @@
|
|||
pub use crate::mandelbrot::Bounds;
|
||||
pub use crate::mandelbrot::Mandelbrot;
|
||||
mod mandelbrot;
|
||||
|
|
18
src/main.rs
18
src/main.rs
|
@ -1,5 +1,5 @@
|
|||
use bevy::{prelude::*, render::texture::TextureFormat};
|
||||
use mandelbrot::Mandelbrot;
|
||||
use mandelbrot::{Bounds, Mandelbrot};
|
||||
use std::time::Instant;
|
||||
|
||||
fn main() {
|
||||
|
@ -88,14 +88,16 @@ fn mandelbrot_render_system(
|
|||
let z = scale.zoom;
|
||||
let h = scale.horizontal;
|
||||
let v = scale.vertical;
|
||||
let iters = scale.iterations;
|
||||
let limit = scale.iterations;
|
||||
|
||||
let x = ((-2.5 * z) + h, (1.0 * z) + h);
|
||||
let y = ((-1.0 * z) - v, (1.0 * z) - v);
|
||||
let bounds = Bounds::new(x, y);
|
||||
|
||||
let start = Instant::now();
|
||||
texture.data.copy_from_slice(fractal.generate_scaled_image(
|
||||
((-2.5 * z) + h, (1.0 * z) + h),
|
||||
((-1.0 * z) - v, (1.0 * z) - v),
|
||||
iters,
|
||||
));
|
||||
texture
|
||||
.data
|
||||
.copy_from_slice(fractal.scaled_image(bounds, limit));
|
||||
let _diff = Instant::now() - start;
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +111,7 @@ fn startup(
|
|||
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||
) {
|
||||
let img_size = Vec2::new(Mandelbrot::width() as f32, Mandelbrot::height() as f32);
|
||||
let img_buf = Mandelbrot::new().generate_image().to_vec();
|
||||
let img_buf = Mandelbrot::new().image().to_vec();
|
||||
|
||||
let texture_handle = textures.add(Texture::new(
|
||||
img_size,
|
||||
|
|
|
@ -1,7 +1,43 @@
|
|||
use num_complex::Complex;
|
||||
use rayon::prelude::*;
|
||||
|
||||
const MAX_ITERATIONS: u16 = 512;
|
||||
pub struct Coordinate(usize, usize);
|
||||
|
||||
impl Coordinate {
|
||||
pub fn new(x: usize, y: usize) -> Self {
|
||||
Self(x, y)
|
||||
}
|
||||
|
||||
pub fn x(&self) -> usize {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn y(&self) -> usize {
|
||||
self.1
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Bounds {
|
||||
x: (f64, f64),
|
||||
y: (f64, f64),
|
||||
}
|
||||
|
||||
impl Bounds {
|
||||
pub const fn new(x: (f64, f64), y: (f64, f64)) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
pub fn x(&self) -> (f64, f64) {
|
||||
self.x
|
||||
}
|
||||
|
||||
pub fn y(&self) -> (f64, f64) {
|
||||
self.y
|
||||
}
|
||||
}
|
||||
|
||||
const DEFAULT_MAX_ITERATIONS: u32 = 64;
|
||||
const DEFAULT_BOUNDS: Bounds = Bounds::new((-2.5, 1.0), (-1.0, 1.0));
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Mandelbrot {
|
||||
|
@ -26,33 +62,32 @@ impl Mandelbrot {
|
|||
Self::IMG_HEIGHT
|
||||
}
|
||||
|
||||
pub fn generate_image(&mut self) -> &[u8] {
|
||||
pub fn image(&mut self) -> &[u8] {
|
||||
let max_iters = DEFAULT_MAX_ITERATIONS as f64;
|
||||
|
||||
self.texture_buffer
|
||||
.par_chunks_mut(4)
|
||||
.enumerate()
|
||||
.for_each(|(i, buf)| {
|
||||
let iters = Self::new_escape_time(i, (-2.5, 1.0), (-1.0, 1.0), 64);
|
||||
let normalized_iters = iters / MAX_ITERATIONS as f64;
|
||||
let h = 0.5 + (10.0 * normalized_iters);
|
||||
buf.copy_from_slice(&Self::hsv_to_rgb(h, 0.6, 1.0));
|
||||
let iters = Self::escape_time(i, DEFAULT_BOUNDS, DEFAULT_MAX_ITERATIONS);
|
||||
let normalized_iters = iters / max_iters;
|
||||
|
||||
let h = normalized_iters * 350.0;
|
||||
let v = if iters == max_iters { 0.0 } else { 1.0 };
|
||||
buf.copy_from_slice(&Self::hsv_to_rgb(h, 1.0, v));
|
||||
});
|
||||
|
||||
&self.texture_buffer
|
||||
}
|
||||
|
||||
pub fn generate_scaled_image(
|
||||
&mut self,
|
||||
x_bounds: (f64, f64),
|
||||
y_bounds: (f64, f64),
|
||||
max_iterations: u32,
|
||||
) -> &[u8] {
|
||||
pub fn scaled_image(&mut self, bounds: Bounds, max_iterations: u32) -> &[u8] {
|
||||
self.texture_buffer
|
||||
.par_chunks_mut(4)
|
||||
.enumerate()
|
||||
.for_each(|(i, buf)| {
|
||||
let max_iters = max_iterations as f64;
|
||||
|
||||
let iters = Self::new_escape_time(i, x_bounds, y_bounds, max_iterations);
|
||||
let iters = Self::escape_time(i, bounds, max_iterations);
|
||||
let normalized_iters = iters / max_iters;
|
||||
|
||||
let h = normalized_iters * 350.0;
|
||||
|
@ -63,17 +98,11 @@ impl Mandelbrot {
|
|||
&self.texture_buffer
|
||||
}
|
||||
|
||||
fn new_escape_time(
|
||||
i: usize,
|
||||
x_bounds: (f64, f64),
|
||||
y_bounds: (f64, f64),
|
||||
max_iterations: u32,
|
||||
) -> f64 {
|
||||
let px = i % Self::IMG_WIDTH;
|
||||
let py = i / Self::IMG_WIDTH;
|
||||
let c = Self::coords_to_complex(px, py, x_bounds, y_bounds);
|
||||
fn escape_time(i: usize, bounds: Bounds, max_iterations: u32) -> f64 {
|
||||
let point = Coordinate::new(i % Self::IMG_WIDTH, i / Self::IMG_WIDTH);
|
||||
let c = Self::coords_to_complex(point, bounds);
|
||||
|
||||
Self::new_calc_num_iters(c, max_iterations)
|
||||
Self::count_iterations(c, max_iterations)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -108,7 +137,7 @@ impl Mandelbrot {
|
|||
[r, g, b, a]
|
||||
}
|
||||
|
||||
fn new_calc_num_iters(c: Complex<f64>, max_iterations: u32) -> f64 {
|
||||
fn count_iterations(c: Complex<f64>, max_iterations: u32) -> f64 {
|
||||
let mut z: Complex<f64> = Complex::new(0.0, 0.0);
|
||||
let mut num_iters: u32 = 0;
|
||||
|
||||
|
@ -132,29 +161,26 @@ impl Mandelbrot {
|
|||
}
|
||||
}
|
||||
|
||||
fn coords_to_complex(
|
||||
px: usize,
|
||||
py: usize,
|
||||
x_bounds: (f64, f64),
|
||||
y_bounds: (f64, f64),
|
||||
) -> Complex<f64> {
|
||||
fn coords_to_complex(point: Coordinate, bounds: Bounds) -> Complex<f64> {
|
||||
Complex::new(
|
||||
Self::scale_width(px, x_bounds),
|
||||
Self::scale_height(py, y_bounds),
|
||||
Self::scale_width(point.x(), bounds.x()),
|
||||
Self::scale_height(point.y(), bounds.y()),
|
||||
)
|
||||
}
|
||||
|
||||
fn scale_width(px: usize, x_bounds: (f64, f64)) -> f64 {
|
||||
#[inline]
|
||||
fn scale_width(x: usize, bounds: (f64, f64)) -> f64 {
|
||||
// const X_MIN: f64 = -2.5;
|
||||
// const X_MAX: f64 = 1.0;
|
||||
|
||||
x_bounds.0 + ((x_bounds.1 - x_bounds.0) * (px as f64 - 0.0)) / Self::IMG_WIDTH as f64 - 0.0
|
||||
bounds.0 + ((bounds.1 - bounds.0) * (x as f64 - 0.0)) / Self::IMG_WIDTH as f64 - 0.0
|
||||
}
|
||||
|
||||
fn scale_height(py: usize, y_bounds: (f64, f64)) -> f64 {
|
||||
#[inline]
|
||||
fn scale_height(y: usize, bounds: (f64, f64)) -> f64 {
|
||||
// const Y_MIN: f64 = -1.0;
|
||||
// const Y_MAX: f64 = 1.0;
|
||||
|
||||
y_bounds.0 + ((y_bounds.1 - y_bounds.0) * (py as f64 - 0.0)) / Self::IMG_HEIGHT as f64 - 0.0
|
||||
bounds.0 + ((bounds.1 - bounds.0) * (y as f64 - 0.0)) / Self::IMG_HEIGHT as f64 - 0.0
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue