feat: update to bevy v0.5
This commit is contained in:
parent
b86f6549d3
commit
9d5a84b142
File diff suppressed because it is too large
Load Diff
|
@ -7,6 +7,6 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = "^0.4"
|
bevy = "^0.5"
|
||||||
num-complex = "^0.4"
|
num-complex = "^0.4"
|
||||||
rayon = "^1.5"
|
rayon = "^1.5"
|
||||||
|
|
18
src/main.rs
18
src/main.rs
|
@ -8,7 +8,7 @@ fn main() {
|
||||||
App::build()
|
App::build()
|
||||||
.add_plugins(DefaultPlugins)
|
.add_plugins(DefaultPlugins)
|
||||||
.add_startup_system(startup.system())
|
.add_startup_system(startup.system())
|
||||||
.add_resource(TextureOptions::default())
|
.insert_resource(TextureOptions::default())
|
||||||
.add_system(mandelbrot_render_system.system())
|
.add_system(mandelbrot_render_system.system())
|
||||||
.add_system(transform_mandelbrot_system.system())
|
.add_system(transform_mandelbrot_system.system())
|
||||||
.run();
|
.run();
|
||||||
|
@ -95,12 +95,10 @@ fn mandelbrot_render_system(
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
|
||||||
// FIXME: This will not work due to https://github.com/bevyengine/bevy/issues/1161
|
|
||||||
// The workaround involves "getting a mutable borrow of the ColorMaterial you use to display the Texture"
|
|
||||||
// according to @FrancoisM#2474, a developer of Bevy on Discord
|
|
||||||
texture
|
texture
|
||||||
.data
|
.data
|
||||||
.copy_from_slice(fractal.scaled_image(bounds, limit));
|
.copy_from_slice(fractal.scaled_image(bounds, limit));
|
||||||
|
|
||||||
let _diff = Instant::now() - start;
|
let _diff = Instant::now() - start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,12 +107,14 @@ fn mandelbrot_render_system(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn startup(
|
fn startup(
|
||||||
commands: &mut Commands,
|
mut commands: Commands,
|
||||||
mut textures: ResMut<Assets<Texture>>,
|
mut textures: ResMut<Assets<Texture>>,
|
||||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||||
) {
|
) {
|
||||||
|
let mut fractal = Mandelbrot::default();
|
||||||
|
|
||||||
let texture_size = Extent3d::new(TEXTURE_WIDTH as u32, TEXTURE_HEIGHT as u32, 1);
|
let texture_size = Extent3d::new(TEXTURE_WIDTH as u32, TEXTURE_HEIGHT as u32, 1);
|
||||||
let texture_data = Mandelbrot::new().image().to_vec();
|
let texture_data = fractal.image().to_vec();
|
||||||
|
|
||||||
let texture_handle = textures.add(Texture::new(
|
let texture_handle = textures.add(Texture::new(
|
||||||
texture_size,
|
texture_size,
|
||||||
|
@ -123,11 +123,11 @@ fn startup(
|
||||||
TextureFormat::Rgba8UnormSrgb,
|
TextureFormat::Rgba8UnormSrgb,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
commands.spawn_bundle(OrthographicCameraBundle::new_2d());
|
||||||
commands
|
commands
|
||||||
.spawn(Camera2dBundle::default())
|
.spawn_bundle(SpriteBundle {
|
||||||
.spawn(SpriteBundle {
|
|
||||||
material: materials.add(texture_handle.into()),
|
material: materials.add(texture_handle.into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.with(Mandelbrot::new());
|
.insert(fractal);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,15 @@ impl Coordinate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Coordinate {
|
||||||
|
pub fn into_complex(self, bounds: Bounds) -> Complex<f64> {
|
||||||
|
Complex::new(
|
||||||
|
Mandelbrot::scale_width(self.x(), bounds.x()),
|
||||||
|
Mandelbrot::scale_height(self.y(), bounds.y()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Bounds {
|
pub struct Bounds {
|
||||||
x: (f64, f64),
|
x: (f64, f64),
|
||||||
|
@ -45,25 +54,33 @@ pub struct Mandelbrot {
|
||||||
frame_buffer: Box<[u8; (TEXTURE_WIDTH * TEXTURE_HEIGHT) * 4]>,
|
frame_buffer: Box<[u8; (TEXTURE_WIDTH * TEXTURE_HEIGHT) * 4]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mandelbrot {
|
impl Default for Mandelbrot {
|
||||||
pub fn new() -> Self {
|
fn default() -> Self {
|
||||||
Mandelbrot {
|
Mandelbrot {
|
||||||
frame_buffer: Box::new([0; (TEXTURE_WIDTH * TEXTURE_HEIGHT) * 4]),
|
frame_buffer: Box::new([0; (TEXTURE_WIDTH * TEXTURE_HEIGHT) * 4]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mandelbrot {
|
||||||
pub fn image(&mut self) -> &[u8] {
|
pub fn image(&mut self) -> &[u8] {
|
||||||
let limit_f64 = DEFAULT_ITERATION_LIMIT as f64;
|
let limit = DEFAULT_ITERATION_LIMIT as f64;
|
||||||
|
let error = f64::EPSILON;
|
||||||
|
|
||||||
self.frame_buffer
|
self.frame_buffer
|
||||||
.par_chunks_mut(4)
|
.par_chunks_mut(4)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.for_each(|(i, buf)| {
|
.for_each(|(i, buf)| {
|
||||||
let iterations = Self::escape_time(i, DEFAULT_BOUNDS, DEFAULT_ITERATION_LIMIT);
|
let iters = Self::escape_time(i, DEFAULT_BOUNDS, DEFAULT_ITERATION_LIMIT);
|
||||||
let normalized_iters = iterations / limit_f64;
|
let normalized = iters / limit;
|
||||||
|
|
||||||
|
let h = normalized * 350.0;
|
||||||
|
let v = if (iters - limit).abs() < error {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
1.0
|
||||||
|
};
|
||||||
|
|
||||||
let h = normalized_iters * 350.0;
|
|
||||||
let v = if iterations == limit_f64 { 0.0 } else { 1.0 };
|
|
||||||
buf.copy_from_slice(&Self::hsv_to_rgb(h, 1.0, v));
|
buf.copy_from_slice(&Self::hsv_to_rgb(h, 1.0, v));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -71,28 +88,34 @@ impl Mandelbrot {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scaled_image(&mut self, bounds: Bounds, limit: u32) -> &[u8] {
|
pub fn scaled_image(&mut self, bounds: Bounds, limit: u32) -> &[u8] {
|
||||||
|
let error = f64::EPSILON;
|
||||||
|
|
||||||
self.frame_buffer
|
self.frame_buffer
|
||||||
.par_chunks_mut(4)
|
.par_chunks_mut(4)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.for_each(|(i, buf)| {
|
.for_each(|(i, buf)| {
|
||||||
let limit_f64 = limit as f64;
|
let iters = Self::escape_time(i, bounds, limit);
|
||||||
|
let limit = limit as f64;
|
||||||
|
let normalized = iters / limit;
|
||||||
|
|
||||||
let iterations = Self::escape_time(i, bounds, limit);
|
let h = normalized * 350.0;
|
||||||
let normalized_iters = iterations / limit_f64;
|
let v = if (iters - limit).abs() < error {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
1.0
|
||||||
|
};
|
||||||
|
|
||||||
let h = normalized_iters * 350.0;
|
|
||||||
let v = if iterations == limit_f64 { 0.0 } else { 1.0 };
|
|
||||||
buf.copy_from_slice(&Self::hsv_to_rgb(h, 1.0, v))
|
buf.copy_from_slice(&Self::hsv_to_rgb(h, 1.0, v))
|
||||||
});
|
});
|
||||||
|
|
||||||
self.frame_buffer.as_ref()
|
self.frame_buffer.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn escape_time(i: usize, bounds: Bounds, iteration_limit: u32) -> f64 {
|
fn escape_time(i: usize, bounds: Bounds, limit: u32) -> f64 {
|
||||||
let point = Coordinate::new(i % TEXTURE_WIDTH, i / TEXTURE_WIDTH);
|
let point = Coordinate::new(i % TEXTURE_WIDTH, i / TEXTURE_WIDTH);
|
||||||
let c = Self::coords_to_complex(point, bounds);
|
let c = point.into_complex(bounds);
|
||||||
|
|
||||||
Self::count_iterations(c, iteration_limit)
|
Self::count_iterations(c, limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -127,16 +150,16 @@ impl Mandelbrot {
|
||||||
[r, g, b, a]
|
[r, g, b, a]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count_iterations(c: Complex<f64>, maximum: u32) -> f64 {
|
fn count_iterations(c: Complex<f64>, limit: 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 count: u32 = 0;
|
let mut count: u32 = 0;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if z.norm_sqr() > 4.0 {
|
if count == limit {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if count >= maximum {
|
if z.norm_sqr() > 4.0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,20 +167,13 @@ impl Mandelbrot {
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if count < maximum {
|
if count < limit {
|
||||||
(count as f64 + 1.0) - z.norm().ln().ln() / 2f64.ln()
|
(count as f64 + 1.0) - z.norm().ln().ln() / 2f64.ln()
|
||||||
} else {
|
} else {
|
||||||
count as f64
|
count as f64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn coords_to_complex(point: Coordinate, bounds: Bounds) -> Complex<f64> {
|
|
||||||
Complex::new(
|
|
||||||
Self::scale_width(point.x(), bounds.x()),
|
|
||||||
Self::scale_height(point.y(), bounds.y()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn scale_width(x: usize, bounds: (f64, f64)) -> f64 {
|
fn scale_width(x: usize, bounds: (f64, f64)) -> f64 {
|
||||||
// const X_MIN: f64 = -2.5;
|
// const X_MIN: f64 = -2.5;
|
||||||
|
|
Loading…
Reference in New Issue