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