diff --git a/examples/noise_fractal_2d/README.md b/examples/noise_fractal_2d/README.md new file mode 100644 index 000000000..ea94dd58f --- /dev/null +++ b/examples/noise_fractal_2d/README.md @@ -0,0 +1,16 @@ +# Example - noise_fractal_2d 📘 + +This example demonstrates the usage of the V Scientific Library for generating pink noise. + +## Instructions + +1. Ensure you have the V compiler installed. You can download it from [here](https://vlang.io). +2. Ensure you have the VSL installed. You can do it following the [installation guide](https://github.com/vlang/vsl?tab=readme-ov-file#-installation)! +3. Navigate to this directory. +4. Run the example using the following command: + +```sh +v run main.v +``` + +Enjoy exploring the capabilities of the V Scientific Library! 😊 diff --git a/examples/noise_fractal_2d/main.v b/examples/noise_fractal_2d/main.v new file mode 100644 index 000000000..a5ef30d25 --- /dev/null +++ b/examples/noise_fractal_2d/main.v @@ -0,0 +1,54 @@ +module main + +import rand +import vsl.noise +import vsl.plot + +fn main() { + // Creation of the noise generator. + // Other noise functions and dimensions count are available. + rand.seed([u32(3155200429), u32(3208395956)]) + mut generator := noise.Generator.new() + generator.randomize() + + mut x := []f64{} + mut y := []f64{} + mut z := []f64{} + + // 5 layers of simplex noise + octaves := 5 + persistence := 0.5 + + for xx in 0 .. 200 { + for yy in 0 .. 200 { + mut total := 0.0 + mut frequency := 1.0 + mut amplitude := 1.0 + mut max_value := 0.0 + + for _ in 0 .. octaves { + total += generator.simplex_2d(0.03 * xx * frequency, 0.03 * yy * frequency) * amplitude + max_value += amplitude + amplitude *= persistence + frequency *= 2.0 + } + + // Normalize to [-1, 1] + total /= max_value + x << xx + y << yy + z << total + } + } + + mut plt := plot.Plot.new() + plt.heatmap( + x: x + y: y + z: z + ) + plt.layout( + title: 'Pink `fractal` noise 2d example' + ) + plt.show()! +} diff --git a/examples/noise_simplex_2d/README.md b/examples/noise_simplex_2d/README.md new file mode 100644 index 000000000..f21dc9268 --- /dev/null +++ b/examples/noise_simplex_2d/README.md @@ -0,0 +1,16 @@ +# Example - noise_simple_2d 📘 + +This example demonstrates the usage of the V Scientific Library for generating simplex noise. + +## Instructions + +1. Ensure you have the V compiler installed. You can download it from [here](https://vlang.io). +2. Ensure you have the VSL installed. You can do it following the [installation guide](https://github.com/vlang/vsl?tab=readme-ov-file#-installation)! +3. Navigate to this directory. +4. Run the example using the following command: + +```sh +v run main.v +``` + +Enjoy exploring the capabilities of the V Scientific Library! 😊 diff --git a/examples/noise_simplex_2d/main.v b/examples/noise_simplex_2d/main.v new file mode 100644 index 000000000..031441cb3 --- /dev/null +++ b/examples/noise_simplex_2d/main.v @@ -0,0 +1,38 @@ +module main + +import rand +import vsl.noise +import vsl.plot + +fn main() { + // Creation of the noise generator. + // Other noise functions and dimensions count are available. + rand.seed([u32(3155200429), u32(3208395956)]) + mut generator := noise.Generator.new() + generator.randomize() + + mut x := []f64{} + mut y := []f64{} + mut z := []f64{} + + for xx in 0 .. 40 { + for yy in 0 .. 40 { + // We need to scale the coordinates to control the frequency of the noise. + val := generator.simplex_2d(0.03 * xx, 0.03 * yy) + x << xx + y << yy + z << val + } + } + + mut plt := plot.Plot.new() + plt.heatmap( + x: x + y: y + z: z + ) + plt.layout( + title: 'Simplex noise 2d example' + ) + plt.show()! +} diff --git a/noise/noise.v b/noise/noise.v new file mode 100644 index 000000000..f5c1aa994 --- /dev/null +++ b/noise/noise.v @@ -0,0 +1,20 @@ +module noise + +import rand + +// Generator is a struct holding the permutation table used in perlin and simplex noise +pub struct Generator { +mut: + perm []int = rand.shuffle_clone(permutations) or { panic(err) } +} + +// new is a function that return a new Generator struct +pub fn Generator.new() Generator { + return Generator{} +} + +// randomize is a function that shuffle the permutation set inside the Generator struct +// will not shuffle if rand.seed is not changed +pub fn (mut generator Generator) randomize() { + generator.perm = rand.shuffle_clone(permutations) or { panic(err) } +} diff --git a/noise/perlin2d.v b/noise/perlin2d.v index 4e5d2661e..0b60ffda0 100644 --- a/noise/perlin2d.v +++ b/noise/perlin2d.v @@ -1,26 +1,7 @@ module noise -import rand - -// Perlin is a struct that hold the permutation set for perlin noise -pub struct Perlin { -mut: - perm []int = rand.shuffle_clone(permutations) or { panic(err) } -} - -// new is a function that return a new Perlin struct -pub fn Perlin.new() Perlin { - return Perlin{} -} - -// randomize is a function that shuffle the permutation set inside the Perlin struct -// will not shuffle if rand.seed is not changed -pub fn (mut perlin Perlin) randomize() { - perlin.perm = rand.shuffle_clone(permutations) or { panic(err) } -} - // perlin2d is a function that return a single value of perlin noise for a given 2d position -pub fn (perlin Perlin) perlin2d(x f64, y f64) f64 { +pub fn (generator Generator) perlin2d(x f64, y f64) f64 { xi := int(x) & 0xFF yi := int(y) & 0xFF @@ -30,13 +11,13 @@ pub fn (perlin Perlin) perlin2d(x f64, y f64) f64 { u := fade(xf) v := fade(yf) - pxi := perlin.perm[xi] - pxi1 := perlin.perm[xi + 1] + pxi := generator.perm[xi] + pxi1 := generator.perm[xi + 1] - aa := perlin.perm[pxi + yi] - ab := perlin.perm[pxi + yi + 1] - ba := perlin.perm[pxi1 + yi] - bb := perlin.perm[pxi1 + yi + 1] + aa := generator.perm[pxi + yi] + ab := generator.perm[pxi + yi + 1] + ba := generator.perm[pxi1 + yi] + bb := generator.perm[pxi1 + yi + 1] x1 := lerp(grad2d(aa, xf, yf), grad2d(ba, xf - 1, yf), u) x2 := lerp(grad2d(ab, xf, yf - 1), grad2d(bb, xf - 1, yf - 1), u) diff --git a/noise/perlin2d_test.v b/noise/perlin2d_test.v index 6b4c81d83..f63a5d3e2 100644 --- a/noise/perlin2d_test.v +++ b/noise/perlin2d_test.v @@ -6,7 +6,7 @@ import vsl.float.float64 fn test_perlin2d() { rand.seed([u32(3155200429), u32(3208395956)]) - mut gen := Perlin.new() + mut gen := Generator.new() gen.randomize() result := gen.perlin2d(0.125, 0.125) diff --git a/noise/perlin3d.v b/noise/perlin3d.v index c32a6131e..9b77e820b 100644 --- a/noise/perlin3d.v +++ b/noise/perlin3d.v @@ -1,7 +1,7 @@ module noise // perlin3d is a function that return a single value of perlin noise for a given 3d position -pub fn (perlin Perlin) perlin3d(x f64, y f64, z f64) f64 { +pub fn (generator Generator) perlin3d(x f64, y f64, z f64) f64 { xi := int(x) & 0xFF yi := int(y) & 0xFF zi := int(z) & 0xFF @@ -12,21 +12,21 @@ pub fn (perlin Perlin) perlin3d(x f64, y f64, z f64) f64 { v := fade(yf) w := fade(zf) - pxi := perlin.perm[xi] - pxi_yi := perlin.perm[pxi + yi] - pxi_yi1 := perlin.perm[pxi + yi + 1] - pxi1 := perlin.perm[xi + 1] - pxi1_yi := perlin.perm[pxi1 + yi] - pxi1_yi1 := perlin.perm[pxi1 + yi + 1] + pxi := generator.perm[xi] + pxi_yi := generator.perm[pxi + yi] + pxi_yi1 := generator.perm[pxi + yi + 1] + pxi1 := generator.perm[xi + 1] + pxi1_yi := generator.perm[pxi1 + yi] + pxi1_yi1 := generator.perm[pxi1 + yi + 1] - aaa := perlin.perm[pxi_yi + zi] - aba := perlin.perm[pxi_yi1 + zi] - aab := perlin.perm[pxi_yi + zi + 1] - abb := perlin.perm[pxi_yi1 + zi + 1] - baa := perlin.perm[pxi1_yi + zi] - bba := perlin.perm[pxi1_yi1 + zi] - bab := perlin.perm[pxi1_yi + zi + 1] - bbb := perlin.perm[pxi1_yi1 + zi + 1] + aaa := generator.perm[pxi_yi + zi] + aba := generator.perm[pxi_yi1 + zi] + aab := generator.perm[pxi_yi + zi + 1] + abb := generator.perm[pxi_yi1 + zi + 1] + baa := generator.perm[pxi1_yi + zi] + bba := generator.perm[pxi1_yi1 + zi] + bab := generator.perm[pxi1_yi + zi + 1] + bbb := generator.perm[pxi1_yi1 + zi + 1] mut x1 := lerp(grad3d(aaa, xf, yf, zf), grad3d(baa, xf - 1, yf, zf), u) mut x2 := lerp(grad3d(aba, xf, yf - 1, zf), grad3d(bba, xf - 1, yf - 1, zf), u) diff --git a/noise/perlin3d_test.v b/noise/perlin3d_test.v index 8edde204c..0f5a67aed 100644 --- a/noise/perlin3d_test.v +++ b/noise/perlin3d_test.v @@ -6,7 +6,7 @@ import vsl.float.float64 fn test_perlin3d() { rand.seed([u32(3155200429), u32(3208395956)]) - mut gen := Perlin.new() + mut gen := Generator.new() gen.randomize() result := gen.perlin3d(0.125, 0.125, 0.125) diff --git a/noise/simplex.v b/noise/simplex.v new file mode 100644 index 000000000..176fe40a6 --- /dev/null +++ b/noise/simplex.v @@ -0,0 +1,389 @@ +module noise + +import math + +// skewing factors for 2D case +const f2 = 0.5 * (math.sqrt(3.0) - 1.0) +const g2 = (3.0 - math.sqrt(3)) / 6.0 +// skewing factors for 3D case +const f3 = f64(1.0 / 3.0) +const g3 = f64(1.0 / 6.0) +// skewing factors for 4D case +const f4 = f64((math.sqrt(5.0) - 1.0) / 4) +const g4 = f64((5.0 - math.sqrt(5.0)) / 20.0) + +// vfmt off +const simplex := [ + [0, 1, 2, 3], [0, 1, 3, 2], [0, 0, 0, 0], [0, 2, 3, 1], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 2, 3, 0], + [0, 2, 1, 3], [0, 0, 0, 0], [0, 3, 1, 2], [0, 3, 2, 1], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 3, 2, 0], + [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], + [1, 2, 0, 3], [0, 0, 0, 0], [1, 3, 0, 2], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [2, 3, 0, 1], [2, 3, 1, 0], + [1, 0, 2, 3], [1, 0, 3, 2], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [2, 0, 3, 1], [0, 0, 0, 0], [2, 1, 3, 0], + [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], + [2, 0, 1, 3], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [3, 0, 1, 2], [3, 0, 2, 1], [0, 0, 0, 0], [3, 1, 2, 0], + [2, 1, 0, 3], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [3, 1, 0, 2], [0, 0, 0, 0], [3, 2, 0, 1], [3, 2, 1, 0] +] +// vfmt on + +// grad_1d returns a gradient value for a given hash and x position +fn grad_1d(hash int, x f64) f64 { + h := hash & 15 + mut grad := 1.0 + f64(h & 7) + grad = if h & 8 == 0 { grad } else { -grad } + return grad * x +} + +// grad_2d returns a gradient value for a given hash and x, y position +fn grad_2d(hash int, x f64, y f64) f64 { + h := hash & 7 + u := if h < 4 { x } else { y } + v := if h < 4 { y } else { x } + return (if h & 1 == 0 { + u + } else { + -u + }) + (if h & 2 == 0 { + 2.0 * v + } else { + -2.0 * v + }) +} + +// grad_3d returns a gradient value for a given hash and x, y, z position +fn grad_3d(hash int, x f64, y f64, z f64) f64 { + h := hash & 15 + u := if h < 8 { x } else { y } + v := if h < 4 { + y + } else { + if h == 12 || h == 14 { x } else { z } + } + return (if h & 1 == 0 { + u + } else { + -u + }) + (if h & 2 == 0 { + v + } else { + -v + }) +} + +// grad_4d returns a gradient value for a given hash and x, y, z, t position +fn grad_4d(hash int, x f64, y f64, z f64, t f64) f64 { + h := hash & 31 + u := if h < 24 { x } else { y } + v := if h < 16 { y } else { z } + w := if h < 8 { z } else { t } + return (if h & 1 == 0 { + u + } else { + -u + }) + (if h & 2 == 0 { + v + } else { + -v + }) + (if h & 4 == 0 { + w + } else { + -w + }) +} + +// simplex_1d returns a simplex noise value for a given x position +pub fn (generator Generator) simplex_1d(x f64) f64 { + i0 := int(x) + i1 := i0 + 1 + x0 := x - i0 + x1 := x0 - 1 + + mut t0 := 1.0 - x0 * x0 + t0 *= t0 + n0 := t0 * t0 * grad_1d(generator.perm[i0 & 0xff], x0) + + mut t1 := 1.0 - x1 * x1 + t1 *= t1 + n1 := t1 * t1 * grad_1d(generator.perm[i1 & 0xff], x1) + + return 0.395 * (n0 + n1) +} + +// simplex_2d returns a simplex noise value for a given x, y position +pub fn (generator Generator) simplex_2d(x f64, y f64) f64 { + s := (x + y) * noise.f2 + i := int(x + s) + j := int(y + s) + + t := f64(i + j) * noise.g2 + x0 := x - (i - t) + y0 := y - (j - t) + + i1, j1 := if x0 > y0 { + 1, 0 + } else { + 0, 1 + } + + x1 := x0 - f64(i1) + noise.g2 + y1 := y0 - f64(j1) + noise.g2 + x2 := x0 - 1.0 + noise.g2 * 2.0 + y2 := y0 - 1.0 + noise.g2 * 2.0 + + ii := i & 0xff + jj := j & 0xff + + mut t0 := 0.5 - x0 * x0 - y0 * y0 + mut n0 := 0.0 + if t0 < 0 { + n0 = 0.0 + } else { + t0 *= t0 + n0 = t0 * t0 * grad_2d(generator.perm[ii + generator.perm[jj]], x0, y0) + } + + mut t1 := 0.5 - x1 * x1 - y1 * y1 + mut n1 := 0.0 + if t1 < 0 { + n1 = 0.0 + } else { + t1 *= t1 + n1 = t1 * t1 * grad_2d(generator.perm[ii + i1 + generator.perm[jj + j1]], x1, + y1) + } + + mut t2 := 0.5 - x2 * x2 - y2 * y2 + mut n2 := 0.0 + if t2 < 0 { + n2 = 0.0 + } else { + t2 *= t2 + n2 = t2 * t2 * grad_2d(generator.perm[ii + 1 + generator.perm[jj + 1]], x2, y2) + } + + return 40.0 * (n0 + n1 + n2) +} + +// simplex_3d returns a simplex noise value for a given x, y, z position +pub fn (generator Generator) simplex_3d(x f64, y f64, z f64) f64 { + s := (x + y + z) * noise.f3 + xs := x + s + ys := y + s + zs := z + s + i := int(xs) + j := int(ys) + k := int(zs) + + t := f64(i + j + k) * noise.g3 + x0 := x - (i - t) + y0 := y - (j - t) + z0 := z - (k - t) + + mut i1 := 0 + mut j1 := 0 + mut k1 := 0 + mut i2 := 0 + mut j2 := 0 + mut k2 := 0 + + if x0 >= y0 { + if y0 >= z0 { + i1 = 1 + i2 = 1 + j2 = 1 + } else if x0 >= z0 { + i1 = 1 + i2 = 1 + k2 = 1 + } else { + k1 = 1 + i2 = 1 + k2 = 1 + } + } else { + if y0 < z0 { + k1 = 1 + j2 = 1 + k2 = 1 + } else if x0 < z0 { + j1 = 1 + j2 = 1 + k2 = 1 + } else { + j1 = 1 + i2 = 1 + j2 = 1 + } + } + + x1 := x0 - i1 + noise.g3 + y1 := y0 - j1 + noise.g3 + z1 := z0 - k1 + noise.g3 + x2 := x0 - i2 + 2.0 * noise.g3 + y2 := y0 - j2 + 2.0 * noise.g3 + z2 := z0 - k2 + 2.0 * noise.g3 + x3 := x0 - 1.0 + 3.0 * noise.g3 + y3 := y0 - 1.0 + 3.0 * noise.g3 + z3 := z0 - 1.0 + 3.0 * noise.g3 + + ii := i & 0xff + jj := j & 0xff + kk := k & 0xff + + mut t0 := 0.6 - x0 * x0 - y0 * y0 - z0 * z0 + mut n0 := 0.0 + if t0 < 0 { + n0 = 0.0 + } else { + t0 *= t0 + n0 = t0 * t0 * grad_3d(generator.perm[ii + generator.perm[jj + generator.perm[kk]]], + x0, y0, z0) + } + + mut t1 := 0.6 - x1 * x1 - y1 * y1 - z1 * z1 + mut n1 := 0.0 + if t1 < 0 { + n1 = 0.0 + } else { + t1 *= t1 + n1 = t1 * t1 * grad_3d(generator.perm[ii + i1 + generator.perm[jj + j1 + generator.perm[kk + + k1]]], x1, y1, z1) + } + + mut t2 := 0.6 - x2 * x2 - y2 * y2 - z2 * z2 + mut n2 := 0.0 + if t2 < 0 { + n2 = 0.0 + } else { + t2 *= t2 + n2 = t2 * t2 * grad_3d(generator.perm[ii + i2 + generator.perm[jj + j2 + generator.perm[kk + + k2]]], x2, y2, z2) + } + + mut t3 := 0.6 - x3 * x3 - y3 * y3 - z3 * z3 + mut n3 := 0.0 + if t3 < 0 { + n3 = 0.0 + } else { + t3 *= t3 + n3 = t3 * t3 * grad_3d(generator.perm[ii + 1 + generator.perm[jj + 1 + generator.perm[kk + + 1]]], x3, y3, z3) + } + + return 32.0 * (n0 + n1 + n2 + n3) +} + +// simplex_4d returns a simplex noise value for a given x, y, z, w position +pub fn (generator Generator) simplex_4d(x f64, y f64, z f64, w f64) f64 { + s := (x + y + z + w) * noise.f4 + xs := x + s + ys := y + s + zs := z + s + ws := w + s + i := int(xs) + j := int(ys) + k := int(zs) + l := int(ws) + + t := f64(i + j + k + l) * noise.g4 + x0 := x - (i - t) + y0 := y - (j - t) + z0 := z - (k - t) + w0 := w - (l - t) + + c1 := if x0 > y0 { 32 } else { 0 } + c2 := if x0 > z0 { 16 } else { 0 } + c3 := if y0 > z0 { 8 } else { 0 } + c4 := if x0 > w0 { 4 } else { 0 } + c5 := if y0 > w0 { 2 } else { 0 } + c6 := if z0 > w0 { 1 } else { 0 } + c := c1 + c2 + c3 + c4 + c5 + c6 + + i1 := if noise.simplex[c][0] >= 3 { 1 } else { 0 } + j1 := if noise.simplex[c][1] >= 3 { 1 } else { 0 } + k1 := if noise.simplex[c][2] >= 3 { 1 } else { 0 } + l1 := if noise.simplex[c][3] >= 3 { 1 } else { 0 } + + i2 := if noise.simplex[c][0] >= 2 { 1 } else { 0 } + j2 := if noise.simplex[c][1] >= 2 { 1 } else { 0 } + k2 := if noise.simplex[c][2] >= 2 { 1 } else { 0 } + l2 := if noise.simplex[c][3] >= 2 { 1 } else { 0 } + + i3 := if noise.simplex[c][0] >= 1 { 1 } else { 0 } + j3 := if noise.simplex[c][1] >= 1 { 1 } else { 0 } + k3 := if noise.simplex[c][2] >= 1 { 1 } else { 0 } + l3 := if noise.simplex[c][3] >= 1 { 1 } else { 0 } + + x1 := x0 - i1 + noise.g4 + y1 := y0 - j1 + noise.g4 + z1 := z0 - k1 + noise.g4 + w1 := w0 - l1 + noise.g4 + x2 := x0 - i2 + 2.0 * noise.g4 + y2 := y0 - j2 + 2.0 * noise.g4 + z2 := z0 - k2 + 2.0 * noise.g4 + w2 := w0 - l2 + 2.0 * noise.g4 + x3 := x0 - i3 + 3.0 * noise.g4 + y3 := y0 - j3 + 3.0 * noise.g4 + z3 := z0 - k3 + 3.0 * noise.g4 + w3 := w0 - l3 + 3.0 * noise.g4 + x4 := x0 - 1.0 + 4.0 * noise.g4 + y4 := y0 - 1.0 + 4.0 * noise.g4 + z4 := z0 - 1.0 + 4.0 * noise.g4 + w4 := w0 - 1.0 + 4.0 * noise.g4 + + ii := i & 0xff + jj := j & 0xff + kk := k & 0xff + ll := l & 0xff + + mut t0 := 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0 + mut n0 := 0.0 + if t0 < 0.0 { + n0 = 0.0 + } else { + t0 *= t0 + n0 = t0 * t0 * grad_4d(generator.perm[ii + generator.perm[jj + generator.perm[kk + + generator.perm[ll]]]], x0, y0, z0, w0) + } + + mut t1 := 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1 + mut n1 := 0.0 + if t1 < 0.0 { + n1 = 0.0 + } else { + t1 *= t1 + n1 = t1 * t1 * grad_4d(generator.perm[ii + i1 + generator.perm[jj + j1 + generator.perm[kk + + k1 + generator.perm[ll + l1]]]], x1, y1, z1, w1) + } + + mut t2 := 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2 + mut n2 := 0.0 + if t2 < 0.0 { + n2 = 0.0 + } else { + t2 *= t2 + n2 = t2 * t2 * grad_4d(generator.perm[ii + i2 + generator.perm[jj + j2 + generator.perm[kk + + k2 + generator.perm[ll + l2]]]], x2, y2, z2, w2) + } + + mut t3 := 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3 + mut n3 := 0.0 + if t3 < 0.0 { + n3 = 0.0 + } else { + t3 *= t3 + n3 = t3 * t3 * grad_4d(generator.perm[ii + i3 + generator.perm[jj + j3 + generator.perm[kk + + k3 + generator.perm[ll + l3]]]], x3, y3, z3, w3) + } + + mut t4 := 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4 + mut n4 := 0.0 + if t4 < 0.0 { + n4 = 0.0 + } else { + t4 *= t4 + n4 = t4 * t4 * grad_4d(generator.perm[ii + 1 + generator.perm[jj + 1 + generator.perm[kk + + 1 + generator.perm[ll + 1]]]], x4, y4, z4, w4) + } + + return 27.0 * (n0 + n1 + n2 + n3 + n4) +} diff --git a/noise/simplex_test.v b/noise/simplex_test.v new file mode 100644 index 000000000..66dd946a7 --- /dev/null +++ b/noise/simplex_test.v @@ -0,0 +1,40 @@ +module noise + +import rand +import vsl.float.float64 + +fn test_simplex_1d() { + rand.seed([u32(3155200429), u32(3208395956)]) + mut generator := Generator.new() + generator.randomize() + result := generator.simplex_1d(0.287) + expected := -0.3544283326507284 + assert float64.tolerance(result, expected, 1.0e-6) +} + +fn test_simplex_2d() { + rand.seed([u32(3075200429), u32(3094395956)]) + mut generator := Generator.new() + generator.randomize() + result := generator.simplex_2d(0.287, 0.475) + expected := -0.09948661872545192 + assert float64.tolerance(result, expected, 1.0e-6) +} + +fn test_simplex_3d() { + rand.seed([u32(3155200429), u32(3208395956)]) + mut generator := Generator.new() + generator.randomize() + result := generator.simplex_3d(0.287, 0.475, 1.917) + expected := -0.06034653476116279 + assert float64.tolerance(result, expected, 1.0e-6) +} + +fn test_simplex_4d() { + rand.seed([u32(3075200429), u32(3094395956)]) + mut generator := Generator.new() + generator.randomize() + result := generator.simplex_4d(0.287, 0.475, 1.917, 0.684) + expected := 0.015098415881100141 + assert float64.tolerance(result, expected, 1.0e-6) +}