Skip to content

Commit

Permalink
Perlin example outputs 2D, 3D and 4D images
Browse files Browse the repository at this point in the history
This required expanding the PlaneMapBuilder a little bit to support
varying dimensions of noise functions. But now the example can be used
to validate that all dimensions of perlin noise continue to output
correct results.
  • Loading branch information
Cifram authored and Razaekel committed Jun 25, 2022
1 parent 0751c33 commit 16db8d0
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 18 deletions.
33 changes: 28 additions & 5 deletions examples/perlin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,46 @@
extern crate noise;

use noise::{utils::*, core::perlin::perlin_3d, permutationtable::PermutationTable};
use noise::{utils::*, core::perlin::{perlin_2d, perlin_3d, perlin_4d}, permutationtable::PermutationTable};

fn main() {
let hasher = PermutationTable::new(0);

PlaneMapBuilder::new_fn(perlin_2d, &hasher)
.set_size(1024, 1024)
.set_x_bounds(-5.0, 5.0)
.set_y_bounds(-5.0, 5.0)
.build()
.write_to_file("perlin_2d_seed=0.png");
PlaneMapBuilder::new_fn(perlin_3d, &hasher)
.set_size(1024, 1024)
.set_x_bounds(-5.0, 5.0)
.set_y_bounds(-5.0, 5.0)
.build()
.write_to_file("perlin_seed=0.png");

.write_to_file("perlin_3d_seed=0.png");
PlaneMapBuilder::new_fn(perlin_4d, &hasher)
.set_size(1024, 1024)
.set_x_bounds(-5.0, 5.0)
.set_y_bounds(-5.0, 5.0)
.build()
.write_to_file("perlin_4d_seed=0.png");

let hasher = PermutationTable::new(1);
PlaneMapBuilder::new_fn(perlin_2d, &hasher)
.set_size(1024, 1024)
.set_x_bounds(-5.0, 5.0)
.set_y_bounds(-5.0, 5.0)
.build()
.write_to_file("perlin_2d_seed=1.png");
PlaneMapBuilder::new_fn(perlin_3d, &hasher)
.set_size(1024, 1024)
.set_x_bounds(-5.0, 5.0)
.set_y_bounds(-5.0, 5.0)
.build()
.write_to_file("perlin_seed=1.png");
.write_to_file("perlin_3d_seed=1.png");
PlaneMapBuilder::new_fn(perlin_4d, &hasher)
.set_size(1024, 1024)
.set_x_bounds(-5.0, 5.0)
.set_y_bounds(-5.0, 5.0)
.build()
.write_to_file("perlin_4d_seed=1.png");
}
34 changes: 21 additions & 13 deletions src/utils/noise_map_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ where
}
}

fn pad_array<const SIZE: usize>(values: &[f64]) -> [f64; SIZE] {
let mut result = [0.0; SIZE];
for i in 0..values.len().min(SIZE) {
result[i] = values[i];
}
result
}

pub trait NoiseMapBuilder<SourceModule> {
fn set_size(self, width: usize, height: usize) -> Self;

Expand Down Expand Up @@ -152,9 +160,9 @@ where
}
}

pub struct PlaneMapBuilder<SourceModule>
pub struct PlaneMapBuilder<SourceModule, const DIM: usize>
where
SourceModule: NoiseFn<f64, 3>,
SourceModule: NoiseFn<f64, DIM>,
{
is_seamless: bool,
x_bounds: (f64, f64),
Expand All @@ -163,10 +171,10 @@ where
source_module: SourceModule,
}

impl<NH, F> PlaneMapBuilder<NoiseFnWrapper<NH, F, 3>>
impl<NH, F, const DIM: usize> PlaneMapBuilder<NoiseFnWrapper<NH, F, DIM>, DIM>
where
NH: NoiseHasher + Clone,
F: Fn([f64; 3], &NH) -> f64,
F: Fn([f64; DIM], &NH) -> f64,
{
pub fn new_fn(func: F, hasher: &NH) -> Self {
PlaneMapBuilder {
Expand All @@ -182,9 +190,9 @@ where
}
}

impl<SourceModule> PlaneMapBuilder<SourceModule>
impl<SourceModule, const DIM: usize> PlaneMapBuilder<SourceModule, DIM>
where
SourceModule: NoiseFn<f64, 3>,
SourceModule: NoiseFn<f64, DIM>,
{
pub fn new(source_module: SourceModule) -> Self {
PlaneMapBuilder {
Expand Down Expand Up @@ -226,9 +234,9 @@ where
}
}

impl<SourceModule> NoiseMapBuilder<SourceModule> for PlaneMapBuilder<SourceModule>
impl<SourceModule, const DIM: usize> NoiseMapBuilder<SourceModule> for PlaneMapBuilder<SourceModule, DIM>
where
SourceModule: NoiseFn<f64, 3>,
SourceModule: NoiseFn<f64, DIM>,
{
fn set_size(self, width: usize, height: usize) -> Self {
PlaneMapBuilder {
Expand Down Expand Up @@ -266,16 +274,16 @@ where
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 sw_value = self.source_module.get(pad_array(&[current_x, current_y]));
let se_value = self
.source_module
.get([current_x + x_extent, current_y, 0.0]);
.get(pad_array(&[current_x + x_extent, current_y]));
let nw_value = self
.source_module
.get([current_x, current_y + y_extent, 0.0]);
.get(pad_array(&[current_x, current_y + y_extent]));
let ne_value =
self.source_module
.get([current_x + x_extent, current_y + y_extent, 0.0]);
.get(pad_array(&[current_x + x_extent, current_y + y_extent]));

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);
Expand All @@ -285,7 +293,7 @@ where

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

result_map[(x, y)] = final_value;
Expand Down

0 comments on commit 16db8d0

Please # to comment.