Skip to content

Instantly share code, notes, and snippets.

@mhsjlw mhsjlw/noise.rs Secret
Created Feb 12, 2017

Embed
What would you like to do?
extern crate rand;
extern crate num_traits;
use rand::{thread_rng, Rng};
use self::num_traits::Float;
trait Noise {
fn compute(&self, x: f64, z: f64) -> f64;
}
struct PerlinNoise {
permutations: Vec<i32>
}
impl Noise for PerlinNoise {
fn new() -> PerlinNoise {
let mut rng = thread_rng(); // hmm... seeded?
let mut permutations: Vec<i32> = vec![0; 512];
for count in 0..256 {
permutations[count] = count as i32;
}
for count in 0..256 {
let ind = rng.gen_range(0, 256 - count) + count;
let val = permutations[count];
permutations[count] = permutations[ind];
permutations[ind] = val;
permutations[count + 256] = permutations[count];
}
return PerlinNoise {
permutations: permutations
}
}
fn fade(&self, t: f64) -> f64 {
return t * t * t * (t * (t * 6f64 - 15f64) + 10f64);
}
fn lerp(&self, t: f64, a: f64, b: f64) -> f64 {
return a + t * (b - a);
}
fn grad(&self, hash: i32, x: f64, y: f64, z: f64) -> f64 {
let h = hash & 15;
let u = if h < 8 { x } else { y };
let v = if h < 4 { y } else { if h != 12 && h != 14 { z } else { x } };
return if (hash & 1) == 0 { u } else { -u } + ( if (hash & 2) == 0 { v } else { -v });
}
fn compute(&self, x: f64, z: f64) -> f64 {
let fx: i32 = x.floor() as i32 & 255;
let fz: i32 = z.floor() as i32 & 255;
x -= x.floor();
z -= z.floor();
let u = self.fade(x);
let w = self.fade(z);
let a = self.permutations[(self.permutations[fx as usize] + fz + 1) as usize];
let b = self.permutations[(self.permutations[fx as usize] + fz) as usize];
let px = self.permutations[(self.permutations[(fx + 1) as usize] + fz + 1) as usize];
let pz = self.permutations[(self.permutations[(px + 1) as usize] + fz) as usize];
return self.lerp(0f64, self.lerp(w, self.lerp(u, self.grad(self.permutations[b as usize], x, z, 0f64), self.grad(self.permutations[pz as usize], x - 1.0 as f64, z, 0f64)), self.lerp(u, self.grad(self.permutations[a as usize], x, z - 1.0 as f64, 0f64), self.grad(self.permutations[px as usize], x - 1.0 as f64, z - 1.0 as f64, 0f64))), self.lerp(w, self.lerp(u, self.grad(self.permutations[(b + 1) as usize], x, z, -1f64), self.grad(self.permutations[(pz + 1) as usize], x - 1.0 as f64, z, -1f64)), self.lerp(u, self.grad(self.permutations[(a + 1) as usize], x, z - 1.0 as f64, -1f64), self.grad(self.permutations[(px + 1) as usize], x - 1.0 as f64, z - 1.0 as f64, -1f64))));
}
}
struct OctaveNoise {
algs: Vec<PerlinNoise>,
count: i32
}
impl Noise for OctaveNoise {
fn new(count: i32) -> OctaveNoise {
let algs = (0..count).map(|_| PerlinNoise::new()).collect();
OctaveNoise {
algs: algs,
count: count
}
}
fn compute(&self, x: f64, z: f64) -> f64 {
let mut result = 0f64;
let mut amp = 1f64;
for i in 0..self.count {
result += self.algs[i as usize].compute(x / amp, z / amp) * amp;
amp *= 2f64;
}
return result;
}
}
struct CombinedNoise<T: Noise> {
noise1: T,
noise2: T,
}
impl<T: Noise> Noise for CombinedNoise<T> {
fn new() -> CombinedNoise {
CombinedNoise {
// instantiate
}
}
fn compute(&self, z: f64, z: f64) -> f64 {
return self.noise1.compute(x + self.noise2.compute(x, z), z)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.