Skip to content

Commit

Permalink
Use generics for NoiseHasher in the core functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Razaekel committed Oct 5, 2021
1 parent 89d0527 commit ba10fd6
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 146 deletions.
58 changes: 33 additions & 25 deletions src/core/open_simplex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@ use crate::{
permutationtable::NoiseHasher,
};

pub fn open_simplex_2d(point: [f64; 2], hasher: &impl NoiseHasher) -> f64 {
pub fn open_simplex_2d<NH>(point: [f64; 2], hasher: &NH) -> f64
where
NH: NoiseHasher + ?Sized,
{
const STRETCH_CONSTANT: f64 = -0.211_324_865_405_187; //(1/sqrt(2+1)-1)/2;
const SQUISH_CONSTANT: f64 = 0.366_025_403_784_439; //(sqrt(2+1)-1)/2;
const NORM_CONSTANT: f64 = 1.0 / 14.0;

fn gradient(hasher: &impl NoiseHasher, vertex: Vector2<f64>, pos: Vector2<f64>) -> f64 {
let attn = 2.0 - pos.magnitude_squared();
fn surflet(index: usize, point: Vector2<f64>) -> f64 {
let t = 2.0 - point.magnitude_squared();

if attn > 0.0 {
let index = hasher.hash(&vertex.numcast().unwrap().into_array());
let vec = Vector2::from(gradient::grad2(index));
attn.powi(4) * pos.dot(vec)
if t > 0.0 {
let gradient = Vector2::from(gradient::grad2(index));
t.powi(4) * point.dot(gradient)
} else {
0.0
}
Expand Down Expand Up @@ -48,9 +50,10 @@ pub fn open_simplex_2d(point: [f64; 2], hasher: &impl NoiseHasher) -> f64 {
{
let offset = Vector2::new($x, $y);
let vertex = stretched_floor + offset;
let index = hasher.hash(&vertex.numcast().unwrap().into_array());
let dpos = rel_pos - (Vector2::broadcast(SQUISH_CONSTANT) * offset.sum()) - offset;

gradient(hasher, vertex, dpos)
surflet(index, dpos)
}
}
);
Expand Down Expand Up @@ -82,18 +85,20 @@ pub fn open_simplex_2d(point: [f64; 2], hasher: &impl NoiseHasher) -> f64 {
value * NORM_CONSTANT
}

pub fn open_simplex_3d(point: [f64; 3], hasher: &impl NoiseHasher) -> f64 {
pub fn open_simplex_3d<NH>(point: [f64; 3], hasher: &NH) -> f64
where
NH: NoiseHasher,
{
const STRETCH_CONSTANT: f64 = -1.0 / 6.0; //(1/Math.sqrt(3+1)-1)/3;
const SQUISH_CONSTANT: f64 = 1.0 / 3.0; //(Math.sqrt(3+1)-1)/3;
const NORM_CONSTANT: f64 = 1.0 / 14.0;

fn gradient(hasher: &impl NoiseHasher, vertex: Vector3<f64>, pos: Vector3<f64>) -> f64 {
let attn = 2.0 - pos.magnitude_squared();
fn surflet(index: usize, point: Vector3<f64>) -> f64 {
let t = 2.0 - point.magnitude_squared();

if attn > 0.0 {
let index = hasher.hash(&vertex.numcast().unwrap().into_array());
let vec = Vector3::from(gradient::grad3(index));
attn.powi(4) * pos.dot(vec)
if t > 0.0 {
let gradient = Vector3::from(gradient::grad3(index));
t.powi(4) * point.dot(gradient)
} else {
0.0
}
Expand Down Expand Up @@ -128,9 +133,10 @@ pub fn open_simplex_3d(point: [f64; 3], hasher: &impl NoiseHasher) -> f64 {
{
let offset = Vector3::new($x, $y, $z);
let vertex = stretched_floor + offset;
let index = hasher.hash(&vertex.numcast().unwrap().into_array());
let dpos = rel_pos - (Vector3::broadcast(SQUISH_CONSTANT) * offset.sum()) - offset;

gradient(hasher, vertex, dpos)
surflet(index, dpos)
}
}
);
Expand Down Expand Up @@ -190,20 +196,21 @@ pub fn open_simplex_3d(point: [f64; 3], hasher: &impl NoiseHasher) -> f64 {
value * NORM_CONSTANT
}

pub fn open_simplex_4d(point: [f64; 4], hasher: &impl NoiseHasher) -> f64 {
pub fn open_simplex_4d<NH>(point: [f64; 4], hasher: &NH) -> f64
where
NH: NoiseHasher + ?Sized,
{
const STRETCH_CONSTANT: f64 = -0.138_196_601_125_011; //(Math.sqrt(4+1)-1)/4;
const SQUISH_CONSTANT: f64 = 0.309_016_994_374_947; //(Math.sqrt(4+1)-1)/4;

const NORM_CONSTANT: f64 = 1.0 / 6.869_909_007_095_662_5;

#[inline(always)]
fn gradient(hasher: &impl NoiseHasher, vertex: Vector4<f64>, pos: Vector4<f64>) -> f64 {
let attn = 2.0 - pos.magnitude_squared();
fn surflet(index: usize, point: Vector4<f64>) -> f64 {
let t = 2.0 - point.magnitude_squared();

if attn > 0.0 {
let index = hasher.hash(&vertex.numcast().unwrap().into_array());
let vec = Vector4::from(gradient::grad4(index));
attn.powi(4) * pos.dot(vec)
if t > 0.0 {
let gradient = Vector4::from(gradient::grad4(index));
t.powi(4) * point.dot(gradient)
} else {
0.0
}
Expand Down Expand Up @@ -240,9 +247,10 @@ pub fn open_simplex_4d(point: [f64; 4], hasher: &impl NoiseHasher) -> f64 {
{
let offset = Vector4::new($x, $y, $z, $w);
let vertex = stretched_floor + offset;
let index = hasher.hash(&vertex.numcast().unwrap().into_array());
let dpos = rel_pos - (Vector4::broadcast(SQUISH_CONSTANT) * offset.sum()) - offset;

gradient(hasher, vertex, dpos)
surflet(index, dpos)
}
}
);
Expand Down
15 changes: 12 additions & 3 deletions src/core/perlin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use crate::{
use core::f64;

#[inline(always)]
pub fn perlin_2d(point: [f64; 2], hasher: &dyn NoiseHasher) -> f64 {
pub fn perlin_2d<NH>(point: [f64; 2], hasher: &NH) -> f64
where
NH: NoiseHasher + ?Sized,
{
// Unscaled range of linearly interpolated perlin noise should be (-sqrt(N)/2, sqrt(N)/2).
// Need to invert this value and multiply the unscaled result by the value to get a scaled
// range of (-1, 1).
Expand Down Expand Up @@ -76,7 +79,10 @@ fn bilinear_interpolation(u: f64, v: f64, g00: f64, g01: f64, g10: f64, g11: f64
}

#[inline(always)]
pub fn perlin_3d(point: [f64; 3], hasher: &dyn NoiseHasher) -> f64 {
pub fn perlin_3d<NH>(point: [f64; 3], hasher: &NH) -> f64
where
NH: NoiseHasher + ?Sized,
{
// Unscaled range of linearly interpolated perlin noise should be (-sqrt(N)/2, sqrt(N)/2).
// Need to invert this value and multiply the unscaled result by the value to get a scaled
// range of (-1, 1).
Expand Down Expand Up @@ -159,7 +165,10 @@ pub fn perlin_3d(point: [f64; 3], hasher: &dyn NoiseHasher) -> f64 {
}

#[inline(always)]
pub fn perlin_4d(point: [f64; 4], hasher: &dyn NoiseHasher) -> f64 {
pub fn perlin_4d<NH>(point: [f64; 4], hasher: &NH) -> f64
where
NH: NoiseHasher + ?Sized,
{
// Unscaled range of linearly interpolated perlin noise should be (-sqrt(N)/2, sqrt(N)/2).
// Need to invert this value and multiply the unscaled result by the value to get a scaled
// range of (-1, 1).
Expand Down
49 changes: 27 additions & 22 deletions src/core/perlin_surflet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ use crate::{
};

#[inline(always)]
pub fn perlin_surflet_2d(point: [f64; 2], hasher: &dyn NoiseHasher) -> f64 {
pub fn perlin_surflet_2d<NH>(point: [f64; 2], hasher: &NH) -> f64
where
NH: NoiseHasher + ?Sized,
{
const SCALE_FACTOR: f64 = 3.160_493_827_160_493_7;

#[inline(always)]
fn surflet(hasher: &dyn NoiseHasher, corner: Vector2<isize>, distance: Vector2<f64>) -> f64 {
fn surflet(index: usize, distance: Vector2<f64>) -> f64 {
let attn: f64 = 1.0 - distance.magnitude_squared();

if attn > 0.0 {
attn.powi(4)
* distance.dot(Vector2::from(gradient::grad2(
hasher.hash(&corner.into_array()),
)))
let gradient = Vector2::from(gradient::grad2(index));
attn.powi(4) * distance.dot(gradient)
} else {
0.0
}
Expand All @@ -32,7 +32,8 @@ pub fn perlin_surflet_2d(point: [f64; 2], hasher: &dyn NoiseHasher) -> f64 {
($x:expr, $y:expr) => {
{
let offset = Vector2::new($x, $y);
surflet(hasher, corner + offset, distance - offset.numcast().unwrap())
let index = hasher.hash(&(corner + offset).into_array());
surflet(index, distance - offset.numcast().unwrap())
}
}
);
Expand All @@ -46,18 +47,19 @@ pub fn perlin_surflet_2d(point: [f64; 2], hasher: &dyn NoiseHasher) -> f64 {
((f00 + f10 + f01 + f11) * SCALE_FACTOR).clamp(-1.0, 1.0)
}

pub fn perlin_surflet_3d(point: [f64; 3], hasher: &dyn NoiseHasher) -> f64 {
pub fn perlin_surflet_3d<NH>(point: [f64; 3], hasher: &NH) -> f64
where
NH: NoiseHasher + ?Sized,
{
const SCALE_FACTOR: f64 = 3.889_855_325_553_107_4;

#[inline(always)]
fn surflet(hasher: &dyn NoiseHasher, corner: Vector3<isize>, distance: Vector3<f64>) -> f64 {
fn surflet(index: usize, distance: Vector3<f64>) -> f64 {
let attn: f64 = 1.0 - distance.magnitude_squared();

if attn > 0.0 {
attn.powi(4)
* distance.dot(Vector3::from(gradient::grad3(
hasher.hash(&corner.into_array()),
)))
let gradient = Vector3::from(gradient::grad3(index));
attn.powi(4) * distance.dot(gradient)
} else {
0.0
}
Expand All @@ -73,7 +75,8 @@ pub fn perlin_surflet_3d(point: [f64; 3], hasher: &dyn NoiseHasher) -> f64 {
($x:expr, $y:expr, $z:expr) => {
{
let offset = Vector3::new($x, $y, $z);
surflet(hasher, corner + offset, distance - offset.numcast().unwrap())
let index = hasher.hash(&(corner + offset).into_array());
surflet(index, distance - offset.numcast().unwrap())
}
}
);
Expand All @@ -91,18 +94,19 @@ pub fn perlin_surflet_3d(point: [f64; 3], hasher: &dyn NoiseHasher) -> f64 {
((f000 + f100 + f010 + f110 + f001 + f101 + f011 + f111) * SCALE_FACTOR).clamp(-1.0, 1.0)
}

pub fn perlin_surflet_4d(point: [f64; 4], hasher: &dyn NoiseHasher) -> f64 {
pub fn perlin_surflet_4d<NH>(point: [f64; 4], hasher: &NH) -> f64
where
NH: NoiseHasher + ?Sized,
{
const SCALE_FACTOR: f64 = 4.424_369_240_215_691;

#[inline(always)]
fn surflet(hasher: &dyn NoiseHasher, corner: Vector4<isize>, distance: Vector4<f64>) -> f64 {
fn surflet(index: usize, distance: Vector4<f64>) -> f64 {
let attn: f64 = 1.0 - distance.magnitude_squared();

if attn > 0.0 {
attn.powi(4)
* distance.dot(Vector4::from(gradient::grad4(
hasher.hash(&corner.into_array()),
)))
let gradient = Vector4::from(gradient::grad4(index));
attn.powi(4) * distance.dot(gradient)
} else {
0.0
}
Expand All @@ -118,7 +122,8 @@ pub fn perlin_surflet_4d(point: [f64; 4], hasher: &dyn NoiseHasher) -> f64 {
($x:expr, $y:expr, $z:expr, $w:expr) => {
{
let offset = Vector4::new($x, $y, $z, $w);
surflet(hasher, corner + offset, distance - offset.numcast().unwrap())
let index = hasher.hash(&(corner + offset).into_array());
surflet(index, distance - offset.numcast().unwrap())
}
}
);
Expand Down
46 changes: 29 additions & 17 deletions src/core/simplex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ where
///
/// 1D Simplex Noise with Derivative
#[inline(always)]
pub fn simplex_1d(x: f64, hasher: &dyn NoiseHasher) -> (f64, f64) {
pub fn simplex_1d<NH>(x: f64, hasher: &NH) -> (f64, f64)
where
NH: NoiseHasher + ?Sized,
{
let cell = x.floor() as isize;

let near_distance = x - cell as f64;
Expand Down Expand Up @@ -138,7 +141,10 @@ pub fn simplex_1d(x: f64, hasher: &dyn NoiseHasher) -> (f64, f64) {

#[inline(always)]
#[inline(always)]
pub fn simplex_2d(point: [f64; 2], hasher: &dyn NoiseHasher) -> (f64, [f64; 2]) {
pub fn simplex_2d<NH>(point: [f64; 2], hasher: &NH) -> (f64, [f64; 2])
where
NH: NoiseHasher + ?Sized,
{
let f2: f64 = skew_factor(2);
let g2: f64 = unskew_factor(2);

Expand Down Expand Up @@ -203,21 +209,21 @@ pub fn simplex_2d(point: [f64; 2], hasher: &dyn NoiseHasher) -> (f64, [f64; 2])
// let t = 0.5 - (x * x + y * y);
let t = 0.5 - point.magnitude_squared();

if t <= 0.0 {
// No influence
SurfletComponents::zeros()
} else {
if t > 0.0 {
let gradient = Vector2::from(gradient::grad2(gradient_index));
let t2 = t * t;
let t4 = t2 * t2;

SurfletComponents {
value: t4 * (gradient.dot(point)),
value: t4 * gradient.dot(point),
t,
t2,
t4,
gradient,
}
} else {
// No influence
SurfletComponents::zeros()
}
}

Expand Down Expand Up @@ -258,7 +264,10 @@ pub fn simplex_2d(point: [f64; 2], hasher: &dyn NoiseHasher) -> (f64, [f64; 2])
}

#[inline(always)]
pub fn simplex_3d(point: [f64; 3], hasher: &dyn NoiseHasher) -> (f64, [f64; 3]) {
pub fn simplex_3d<NH>(point: [f64; 3], hasher: &NH) -> (f64, [f64; 3])
where
NH: NoiseHasher + ?Sized,
{
let f3: f64 = skew_factor(3);
let g3: f64 = unskew_factor(3);

Expand Down Expand Up @@ -343,10 +352,7 @@ pub fn simplex_3d(point: [f64; 3], hasher: &dyn NoiseHasher) -> (f64, [f64; 3])
fn surflet(gradient_index: usize, point: Vector3<f64>) -> SurfletComponents {
let t = 0.5 - point.magnitude_squared();

if t <= 0.0 {
// No influence
SurfletComponents::zeros()
} else {
if t > 0.0 {
let gradient = Vector3::from(gradient::grad3(gradient_index));
let t2 = t * t;
let t4 = t2 * t2;
Expand All @@ -358,6 +364,9 @@ pub fn simplex_3d(point: [f64; 3], hasher: &dyn NoiseHasher) -> (f64, [f64; 3])
t4,
gradient,
}
} else {
// No influence
SurfletComponents::zeros()
}
}

Expand Down Expand Up @@ -411,7 +420,10 @@ pub fn simplex_3d(point: [f64; 3], hasher: &dyn NoiseHasher) -> (f64, [f64; 3])
}

#[inline(always)]
pub fn simplex_4d(point: [f64; 4], hasher: &dyn NoiseHasher) -> (f64, [f64; 4]) {
pub fn simplex_4d<NH>(point: [f64; 4], hasher: &NH) -> (f64, [f64; 4])
where
NH: NoiseHasher + ?Sized,
{
let f4: f64 = skew_factor(4);
let g4: f64 = unskew_factor(4);

Expand Down Expand Up @@ -518,10 +530,7 @@ pub fn simplex_4d(point: [f64; 4], hasher: &dyn NoiseHasher) -> (f64, [f64; 4])
fn surflet(gradient_index: usize, point: Vector4<f64>) -> SurfletComponents {
let t = 0.6 - point.magnitude_squared();

if t <= 0.0 {
// No influence
SurfletComponents::zeros()
} else {
if t > 0.0 {
let gradient = Vector4::from(gradient::grad4(gradient_index));
let t2 = t * t;
let t4 = t2 * t2;
Expand All @@ -533,6 +542,9 @@ pub fn simplex_4d(point: [f64; 4], hasher: &dyn NoiseHasher) -> (f64, [f64; 4])
t4,
gradient,
}
} else {
// No influence
SurfletComponents::zeros()
}
}

Expand Down
Loading

0 comments on commit ba10fd6

Please sign in to comment.