Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#212 - Multi-threaded NoiseMapBuilder with Rayon [WIP] #213

Draft
wants to merge 4 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ license = "Apache-2.0/MIT"
keywords = ["math", "random"]
authors = ["The Noise-rs Developers."]

[profile.release]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to leave this in? Enabling debug in release builds is useful for debugging and benchmarking, but it can create release binaries that are very large.

Also, I don't actually know if this has any effect for libraries.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely didn't mean to commit that, feel free to remove.

debug = true

[lib]
name = "noise"

[dependencies]
rand = "0.5"
image = { version = "0.18", optional = true }
rayon = "1.2.0"

[features]
default = ["image"]
Expand Down
63 changes: 38 additions & 25 deletions src/utils/noise_map_builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
extern crate rayon;

use math::interpolate;
use noise_fns::NoiseFn;
use utils::noise_map::NoiseMap;
use std::sync::{Arc, RwLock};
use self::rayon::prelude::*;

pub trait NoiseMapBuilder<'a> {
fn set_size(self, width: usize, height: usize) -> Self;
Expand Down Expand Up @@ -205,36 +209,45 @@ impl<'a> NoiseMapBuilder<'a> for PlaneMapBuilder<'a> {
let x_step = x_extent / width as f64;
let y_step = y_extent / height as f64;

let x_bounds = self.x_bounds;
let y_bounds = self.y_bounds;
let is_seamless = self.is_seamless;

for y in 0..height {
let current_y = self.y_bounds.0 + y_step * y as f64;

for x in 0..width {
let current_x = self.x_bounds.0 + x_step * x as f64;

let final_value = if self.is_seamless {
let sw_value = self.source_module.get([current_x, current_y, 0.0]);
let se_value = self
.source_module
.get([current_x + x_extent, current_y, 0.0]);
let nw_value = self
.source_module
.get([current_x, current_y + y_extent, 0.0]);
let ne_value =
self.source_module
.get([current_x + x_extent, current_y + y_extent, 0.0]);

let x_blend = 1.0 - ((current_x - self.x_bounds.0) / x_extent);
let y_blend = 1.0 - ((current_y - self.y_bounds.0) / y_extent);

let y0 = interpolate::linear(sw_value, se_value, x_blend);
let y1 = interpolate::linear(nw_value, ne_value, x_blend);

interpolate::linear(y0, y1, y_blend)
let locked = RwLock::new(self);

// split tasks into parallel threads, then collect
let final_values: Vec<_> = (0..width).into_par_iter().map(|x| {
let current_x = x_bounds.0 + x_step * x as f64;
let readable = locked.read().unwrap();

let final_value = if is_seamless {
let sw_value = readable.source_module.get([current_x, current_y, 0.0]);
let se_value = readable.source_module
.get([current_x + x_extent, current_y, 0.0]);
let nw_value = readable.source_module
.get([current_x, current_y + y_extent, 0.0]);
let ne_value =
readable.source_module
.get([current_x + x_extent, current_y + y_extent, 0.0]);
let x_blend = 1.0 - ((current_x - x_bounds.0) / x_extent);
let y_blend = 1.0 - ((current_y - y_bounds.0) / y_extent);

let y0 = interpolate::linear(sw_value, se_value, x_blend);
let y1 = interpolate::linear(nw_value, ne_value, x_blend);

interpolate::linear(y0, y1, y_blend)
} else {
self.source_module.get([current_x, current_y, 0.0])
readable.source_module.get([current_x, current_y, 0.0])
};

result_map.set_value(x, y, final_value);
final_value
}).collect();

// write results back to data structure
for x in 0..width {
result_map.set_value(x, y, final_values[x]);
}
}

Expand Down