From dc7e6871eca6e5f5d298873afff3ea45964dcc36 Mon Sep 17 00:00:00 2001 From: PottierLoic Date: Thu, 4 Jul 2024 01:40:23 +0200 Subject: [PATCH 01/11] noise: add simplex 2d implementation --- noise/simplex.v | 82 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 noise/simplex.v diff --git a/noise/simplex.v b/noise/simplex.v new file mode 100644 index 000000000..af5ef84b3 --- /dev/null +++ b/noise/simplex.v @@ -0,0 +1,82 @@ +module noise + +import math + +const f2 = 0.5 * (math.sqrt(3.0) - 1.0) +const g2 = (3.0 - math.sqrt(3)) / 6.0 + +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 + }) +} + +pub fn simplex_2d(x f64, y f64) f64 { + // skew the input space to determine which simplex cell we're in + s := (x + y) * noise.f2 + i := int(x + s) + j := int(y + s) + + // unskew the cell origin back to x, y space + t := f64(i + j) * noise.g2 + // distances from the cell origin + x0 := x - (i - t) + y0 := y - (j - t) + + i1, j1 := if x0 > y0 { + // lower triangle + 1, 0 + } else { + // upper triangle + 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 + + // avoid oob + ii := i & 0xff + jj := j & 0xff + + // calculate the 3 corners + 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(permutations[ii + permutations[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(permutations[ii + i1 + permutations[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(permutations[ii + 1 + permutations[jj + 1]], x2, y2) + } + + // scale the return value to [-1, 1] + return 40.0 * (n0 + n1 + n2) +} From cb9f64977d0c62d7d387ca975f34709708cfd241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Pottier?= Date: Thu, 4 Jul 2024 17:12:42 +0200 Subject: [PATCH 02/11] noise: add simplex 1d/3d implementation --- noise/simplex.v | 199 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) diff --git a/noise/simplex.v b/noise/simplex.v index af5ef84b3..07ad2f217 100644 --- a/noise/simplex.v +++ b/noise/simplex.v @@ -2,8 +2,19 @@ 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) + +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 +} fn grad_2d(hash int, x f64, y f64) f64 { h := hash & 7 @@ -20,6 +31,63 @@ fn grad_2d(hash int, x f64, y f64) f64 { }) } +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 + }) +} + +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 + }) +} + +pub fn 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(permutations[i0 & 0xff], x0) + + mut t1 := 1.0 - x1 * x1 + t1 *= t1 + n1 := t1 * t1 * grad_1d(permutations[i1 & 0xff], x1) + + // we scale it to [-1, 1] + return 0.395 * (n0 + n1) +} + pub fn simplex_2d(x f64, y f64) f64 { // skew the input space to determine which simplex cell we're in s := (x + y) * noise.f2 @@ -80,3 +148,134 @@ pub fn simplex_2d(x f64, y f64) f64 { // scale the return value to [-1, 1] return 40.0 * (n0 + n1 + n2) } + +pub fn simplex_3d(x f64, y f64, z f64) f64 { + // skew the input space to determine which simplex cell we're in + s := (x + y + z) * f3 + xs := x + s + ys := y + s + zs := z + s + i := int(xs) + j := int(ys) + k := int(zs) + + // unskew the cell origin back to x, y, z space + t := f64(i + j + k) * g3 + // distances from cell origin + 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 + j1 = 0 + k1 = 0 + i2 = 1 + j2 = 1 + k2 = 0 + } + else if x0 >= z0 { + i1 = 1 + j1 = 0 + k1 = 0 + i2 = 1 + j2 = 0 + k2 = 1 + } + else { + i1 = 0 + j1 = 0 + k1 = 1 + i2 = 1 + j2 = 0 + k2 = 1 + } + } else { + if y0 < z0 { + i1 = 0 + j1 = 0 + k1 = 1 + i2 = 0 + j2 = 1 + k2 = 1 + } + else if x0 < z0 { + i1 = 0 + j1 = 1 + k1 = 0 + i2 = 0 + j2 = 1 + k2 = 1 + } + else { + i1 = 0 + j1 = 1 + k1 = 0 + i2 = 1 + j2 = 1 + k2 = 0 + } + } + + // offsets for corners in x, y, z coords + x1 := x0 - i1 + g3 + y1 := y0 - j1 + g3 + z1 := z0 - k1 + g3 + x2 := x0 - i2 + 2.0 * g3 + y2 := y0 - j2 + 2.0 * g3 + z2 := z0 - k2 + 2.0 * g3 + x3 := x0 - 1.0 + 3.0 * g3 + y3 := y0 - 1.0 + 3.0 * g3 + z3 := z0 - 1.0 + 3.0 * 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(permutations[ii + permutations[jj + permutations[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(permutations[ii + i1 + permutations[jj + j1 + permutations[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(permutations[ii + i2 + permutations[jj + j2 + permutations[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(permutations[ii + 1 + permutations[jj + 1 + permutations[kk + 1]]], x3, y3, z3) + } + + // scale the return value to [-1, 1] + return 32.0 * (n0 + n1 + n2 + n3) +} From 88a9e481ff3d0aefb88ceb81b2a8a249760e7f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Pottier?= Date: Fri, 5 Jul 2024 17:17:52 +0200 Subject: [PATCH 03/11] noise: add simplex 4d implementation --- noise/simplex.v | 125 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/noise/simplex.v b/noise/simplex.v index 07ad2f217..8448cde4f 100644 --- a/noise/simplex.v +++ b/noise/simplex.v @@ -8,6 +8,21 @@ 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) + + +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] +] fn grad_1d(hash int, x f64) f64 { h := hash & 15 @@ -279,3 +294,113 @@ pub fn simplex_3d(x f64, y f64, z f64) f64 { // scale the return value to [-1, 1] return 32.0 * (n0 + n1 + n2 + n3) } + +pub fn simplex_4d(x f64, y f64, z f64, w f64) f64 { + s := (x + y + z + w) * 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) * 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 simplex[c][0] >= 3 { 1 } else { 0 } + j1 := if simplex[c][1] >= 3 { 1 } else { 0 } + k1 := if simplex[c][2] >= 3 { 1 } else { 0 } + l1 := if simplex[c][3] >= 3 { 1 } else { 0 } + + i2 := if simplex[c][0] >= 2 { 1 } else { 0 } + j2 := if simplex[c][1] >= 2 { 1 } else { 0 } + k2 := if simplex[c][2] >= 2 { 1 } else { 0 } + l2 := if simplex[c][3] >= 2 { 1 } else { 0 } + + i3 := if simplex[c][0] >= 1 { 1 } else { 0 } + j3 := if simplex[c][1] >= 1 { 1 } else { 0 } + k3 := if simplex[c][2] >= 1 { 1 } else { 0 } + l3 := if simplex[c][3] >= 1 { 1 } else { 0 } + + x1 := x0 - i1 + g4 + y1 := y0 - j1 + g4 + z1 := z0 - k1 + g4 + w1 := w0 - l1 + g4 + x2 := x0 - i2 + 2.0 * g4 + y2 := y0 - j2 + 2.0 * g4 + z2 := z0 - k2 + 2.0 * g4 + w2 := w0 - l2 + 2.0 * g4 + x3 := x0 - i3 + 3.0 * g4 + y3 := y0 - j3 + 3.0 * g4 + z3 := z0 - k3 + 3.0 * g4 + w3 := w0 - l3 + 3.0 * g4 + x4 := x0 - 1.0 + 4.0 * g4 + y4 := y0 - 1.0 + 4.0 * g4 + z4 := z0 - 1.0 + 4.0 * g4 + w4 := w0 - 1.0 + 4.0 * 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(permutations[ii + permutations[jj + permutations[kk + permutations[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(permutations[ii + i1 + permutations[jj + j1 + permutations[kk + k1 + permutations[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(permutations[ii + i2 + permutations[jj + j2 + permutations[kk + k2 + permutations[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(permutations[ii + i3 + permutations[jj + j3 + permutations[kk + k3 + permutations[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(permutations[ii + 1 + permutations[jj + 1 + permutations[kk + 1 + permutations[ll + 1]]]], x4, y4, z4, w4) + } + + return 27.0 * (n0 + n1 + n2 + n3 + n4) +} From b0d2484df0d2ad5b9910f1f92cfe56c4b6da2c7d Mon Sep 17 00:00:00 2001 From: PottierLoic Date: Sun, 7 Jul 2024 21:51:39 +0200 Subject: [PATCH 04/11] noise: fmt and clean --- noise/simplex.v | 290 +++++++++++++++++++++++------------------------- 1 file changed, 139 insertions(+), 151 deletions(-) diff --git a/noise/simplex.v b/noise/simplex.v index 8448cde4f..73280f4c6 100644 --- a/noise/simplex.v +++ b/noise/simplex.v @@ -12,7 +12,7 @@ const g3 = f64(1.0 / 6.0) 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], @@ -23,6 +23,7 @@ const simplex := [ [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 fn grad_1d(hash int, x f64) f64 { h := hash & 15 @@ -166,7 +167,7 @@ pub fn simplex_2d(x f64, y f64) f64 { pub fn simplex_3d(x f64, y f64, z f64) f64 { // skew the input space to determine which simplex cell we're in - s := (x + y + z) * f3 + s := (x + y + z) * noise.f3 xs := x + s ys := y + s zs := z + s @@ -175,15 +176,15 @@ pub fn simplex_3d(x f64, y f64, z f64) f64 { k := int(zs) // unskew the cell origin back to x, y, z space - t := f64(i + j + k) * g3 + t := f64(i + j + k) * noise.g3 // distances from cell origin x0 := x - (i - t) y0 := y - (j - t) z0 := z - (k - t) - mut i1 := 0 - mut j1 := 0 - mut k1 := 0 + mut i1 := 0 + mut j1 := 0 + mut k1 := 0 mut i2 := 0 mut j2 := 0 mut k2 := 0 @@ -191,77 +192,56 @@ pub fn simplex_3d(x f64, y f64, z f64) f64 { if x0 >= y0 { if y0 >= z0 { i1 = 1 - j1 = 0 - k1 = 0 i2 = 1 j2 = 1 - k2 = 0 - } - else if x0 >= z0 { + } else if x0 >= z0 { i1 = 1 - j1 = 0 - k1 = 0 i2 = 1 - j2 = 0 k2 = 1 - } - else { - i1 = 0 - j1 = 0 + } else { k1 = 1 i2 = 1 - j2 = 0 k2 = 1 } } else { if y0 < z0 { - i1 = 0 - j1 = 0 k1 = 1 - i2 = 0 j2 = 1 k2 = 1 - } - else if x0 < z0 { - i1 = 0 + } else if x0 < z0 { j1 = 1 - k1 = 0 - i2 = 0 j2 = 1 k2 = 1 - } - else { - i1 = 0 + } else { j1 = 1 - k1 = 0 i2 = 1 j2 = 1 - k2 = 0 } } // offsets for corners in x, y, z coords - x1 := x0 - i1 + g3 - y1 := y0 - j1 + g3 - z1 := z0 - k1 + g3 - x2 := x0 - i2 + 2.0 * g3 - y2 := y0 - j2 + 2.0 * g3 - z2 := z0 - k2 + 2.0 * g3 - x3 := x0 - 1.0 + 3.0 * g3 - y3 := y0 - 1.0 + 3.0 * g3 - z3 := z0 - 1.0 + 3.0 * g3 - - ii := i & 0xff - jj := j & 0xff + 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 { + if t0 < 0 { n0 = 0.0 } else { - t0 *= t0 - n0 = t0 * t0 * grad_3d(permutations[ii + permutations[jj + permutations[kk]]], x0, y0, z0) + t0 *= t0 + n0 = t0 * t0 * grad_3d(permutations[ii + permutations[jj + permutations[kk]]], + x0, y0, z0) } mut t1 := 0.6 - x1 * x1 - y1 * y1 - z1 * z1 @@ -270,7 +250,8 @@ pub fn simplex_3d(x f64, y f64, z f64) f64 { n1 = 0.0 } else { t1 *= t1 - n1 = t1 * t1 * grad_3d(permutations[ii + i1 + permutations[jj + j1 + permutations[kk + k1]]], x1, y1, z1) + n1 = t1 * t1 * grad_3d(permutations[ii + i1 + permutations[jj + j1 + permutations[kk + k1]]], + x1, y1, z1) } mut t2 := 0.6 - x2 * x2 - y2 * y2 - z2 * z2 @@ -279,7 +260,8 @@ pub fn simplex_3d(x f64, y f64, z f64) f64 { n2 = 0.0 } else { t2 *= t2 - n2 = t2 * t2 * grad_3d(permutations[ii + i2 + permutations[jj + j2 + permutations[kk + k2]]], x2, y2, z2) + n2 = t2 * t2 * grad_3d(permutations[ii + i2 + permutations[jj + j2 + permutations[kk + k2]]], + x2, y2, z2) } mut t3 := 0.6 - x3 * x3 - y3 * y3 - z3 * z3 @@ -288,7 +270,8 @@ pub fn simplex_3d(x f64, y f64, z f64) f64 { n3 = 0.0 } else { t3 *= t3 - n3 = t3 * t3 * grad_3d(permutations[ii + 1 + permutations[jj + 1 + permutations[kk + 1]]], x3, y3, z3) + n3 = t3 * t3 * grad_3d(permutations[ii + 1 + permutations[jj + 1 + permutations[kk + 1]]], + x3, y3, z3) } // scale the return value to [-1, 1] @@ -296,111 +279,116 @@ pub fn simplex_3d(x f64, y f64, z f64) f64 { } pub fn simplex_4d(x f64, y f64, z f64, w f64) f64 { - s := (x + y + z + w) * 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) * 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 simplex[c][0] >= 3 { 1 } else { 0 } - j1 := if simplex[c][1] >= 3 { 1 } else { 0 } - k1 := if simplex[c][2] >= 3 { 1 } else { 0 } - l1 := if simplex[c][3] >= 3 { 1 } else { 0 } - - i2 := if simplex[c][0] >= 2 { 1 } else { 0 } - j2 := if simplex[c][1] >= 2 { 1 } else { 0 } - k2 := if simplex[c][2] >= 2 { 1 } else { 0 } - l2 := if simplex[c][3] >= 2 { 1 } else { 0 } - - i3 := if simplex[c][0] >= 1 { 1 } else { 0 } - j3 := if simplex[c][1] >= 1 { 1 } else { 0 } - k3 := if simplex[c][2] >= 1 { 1 } else { 0 } - l3 := if simplex[c][3] >= 1 { 1 } else { 0 } - - x1 := x0 - i1 + g4 - y1 := y0 - j1 + g4 - z1 := z0 - k1 + g4 - w1 := w0 - l1 + g4 - x2 := x0 - i2 + 2.0 * g4 - y2 := y0 - j2 + 2.0 * g4 - z2 := z0 - k2 + 2.0 * g4 - w2 := w0 - l2 + 2.0 * g4 - x3 := x0 - i3 + 3.0 * g4 - y3 := y0 - j3 + 3.0 * g4 - z3 := z0 - k3 + 3.0 * g4 - w3 := w0 - l3 + 3.0 * g4 - x4 := x0 - 1.0 + 4.0 * g4 - y4 := y0 - 1.0 + 4.0 * g4 - z4 := z0 - 1.0 + 4.0 * g4 - w4 := w0 - 1.0 + 4.0 * 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 + 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(permutations[ii + permutations[jj + permutations[kk + permutations[ll]]]], x0, y0, z0, w0) - } - - mut t1 := 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1 - mut n1 := 0.0 + n0 = 0.0 + } else { + t0 *= t0 + n0 = t0 * t0 * grad_4d(permutations[ii + permutations[jj + permutations[kk + + permutations[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(permutations[ii + i1 + permutations[jj + j1 + permutations[kk + k1 + permutations[ll + l1]]]], x1, y1, z1, w1) - } - - mut t2 := 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2 - mut n2 := 0.0 + n1 = 0.0 + } else { + t1 *= t1 + n1 = t1 * t1 * grad_4d(permutations[ii + i1 + permutations[jj + j1 + permutations[kk + k1 + + permutations[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(permutations[ii + i2 + permutations[jj + j2 + permutations[kk + k2 + permutations[ll + l2]]]], x2, y2, z2, w2) - } - - mut t3 := 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3 - mut n3 := 0.0 + n2 = 0.0 + } else { + t2 *= t2 + n2 = t2 * t2 * grad_4d(permutations[ii + i2 + permutations[jj + j2 + permutations[kk + k2 + + permutations[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(permutations[ii + i3 + permutations[jj + j3 + permutations[kk + k3 + permutations[ll + l3]]]], x3, y3, z3, w3) - } - - mut t4 := 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4 - mut n4 := 0.0 + n3 = 0.0 + } else { + t3 *= t3 + n3 = t3 * t3 * grad_4d(permutations[ii + i3 + permutations[jj + j3 + permutations[kk + k3 + + permutations[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(permutations[ii + 1 + permutations[jj + 1 + permutations[kk + 1 + permutations[ll + 1]]]], x4, y4, z4, w4) - } + n4 = 0.0 + } else { + t4 *= t4 + n4 = t4 * t4 * grad_4d(permutations[ii + 1 + permutations[jj + 1 + permutations[kk + 1 + + permutations[ll + 1]]]], x4, y4, z4, w4) + } - return 27.0 * (n0 + n1 + n2 + n3 + n4) + return 27.0 * (n0 + n1 + n2 + n3 + n4) } From 3f64daa88cd40f005bca114e8b58c5aca4efc849 Mon Sep 17 00:00:00 2001 From: PottierLoic Date: Tue, 9 Jul 2024 00:24:59 +0200 Subject: [PATCH 05/11] noise: rename `Perlin` struct to `Generator` and add tests for simplex noise --- noise/noise.v | 20 ++++++++++++++++ noise/perlin2d.v | 33 ++++++--------------------- noise/perlin2d_test.v | 2 +- noise/perlin3d.v | 30 ++++++++++++------------ noise/perlin3d_test.v | 2 +- noise/simplex.v | 53 ++++++++++++++++++++++--------------------- noise/simplex_test.v | 40 ++++++++++++++++++++++++++++++++ 7 files changed, 111 insertions(+), 69 deletions(-) create mode 100644 noise/noise.v create mode 100644 noise/simplex_test.v 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 index 73280f4c6..000466bd3 100644 --- a/noise/simplex.v +++ b/noise/simplex.v @@ -86,7 +86,7 @@ fn grad_4d(hash int, x f64, y f64, z f64, t f64) f64 { }) } -pub fn simplex_1d(x f64) f64 { +pub fn (generator Generator) simplex_1d(x f64) f64 { i0 := int(x) i1 := i0 + 1 x0 := x - i0 @@ -94,17 +94,17 @@ pub fn simplex_1d(x f64) f64 { mut t0 := 1.0 - x0 * x0 t0 *= t0 - n0 := t0 * t0 * grad_1d(permutations[i0 & 0xff], x0) + n0 := t0 * t0 * grad_1d(generator.perm[i0 & 0xff], x0) mut t1 := 1.0 - x1 * x1 t1 *= t1 - n1 := t1 * t1 * grad_1d(permutations[i1 & 0xff], x1) + n1 := t1 * t1 * grad_1d(generator.perm[i1 & 0xff], x1) // we scale it to [-1, 1] return 0.395 * (n0 + n1) } -pub fn simplex_2d(x f64, y f64) f64 { +pub fn (generator Generator) simplex_2d(x f64, y f64) f64 { // skew the input space to determine which simplex cell we're in s := (x + y) * noise.f2 i := int(x + s) @@ -140,7 +140,7 @@ pub fn simplex_2d(x f64, y f64) f64 { n0 = 0.0 } else { t0 *= t0 - n0 = t0 * t0 * grad_2d(permutations[ii + permutations[jj]], x0, y0) + n0 = t0 * t0 * grad_2d(generator.perm[ii + generator.perm[jj]], x0, y0) } mut t1 := 0.5 - x1 * x1 - y1 * y1 @@ -149,7 +149,8 @@ pub fn simplex_2d(x f64, y f64) f64 { n1 = 0.0 } else { t1 *= t1 - n1 = t1 * t1 * grad_2d(permutations[ii + i1 + permutations[jj + j1]], x1, y1) + n1 = t1 * t1 * grad_2d(generator.perm[ii + i1 + generator.perm[jj + j1]], x1, + y1) } mut t2 := 0.5 - x2 * x2 - y2 * y2 @@ -158,14 +159,14 @@ pub fn simplex_2d(x f64, y f64) f64 { n2 = 0.0 } else { t2 *= t2 - n2 = t2 * t2 * grad_2d(permutations[ii + 1 + permutations[jj + 1]], x2, y2) + n2 = t2 * t2 * grad_2d(generator.perm[ii + 1 + generator.perm[jj + 1]], x2, y2) } // scale the return value to [-1, 1] return 40.0 * (n0 + n1 + n2) } -pub fn simplex_3d(x f64, y f64, z f64) f64 { +pub fn (generator Generator) simplex_3d(x f64, y f64, z f64) f64 { // skew the input space to determine which simplex cell we're in s := (x + y + z) * noise.f3 xs := x + s @@ -240,7 +241,7 @@ pub fn simplex_3d(x f64, y f64, z f64) f64 { n0 = 0.0 } else { t0 *= t0 - n0 = t0 * t0 * grad_3d(permutations[ii + permutations[jj + permutations[kk]]], + n0 = t0 * t0 * grad_3d(generator.perm[ii + generator.perm[jj + generator.perm[kk]]], x0, y0, z0) } @@ -250,8 +251,8 @@ pub fn simplex_3d(x f64, y f64, z f64) f64 { n1 = 0.0 } else { t1 *= t1 - n1 = t1 * t1 * grad_3d(permutations[ii + i1 + permutations[jj + j1 + permutations[kk + k1]]], - x1, y1, z1) + 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 @@ -260,8 +261,8 @@ pub fn simplex_3d(x f64, y f64, z f64) f64 { n2 = 0.0 } else { t2 *= t2 - n2 = t2 * t2 * grad_3d(permutations[ii + i2 + permutations[jj + j2 + permutations[kk + k2]]], - x2, y2, z2) + 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 @@ -270,15 +271,15 @@ pub fn simplex_3d(x f64, y f64, z f64) f64 { n3 = 0.0 } else { t3 *= t3 - n3 = t3 * t3 * grad_3d(permutations[ii + 1 + permutations[jj + 1 + permutations[kk + 1]]], - x3, y3, z3) + n3 = t3 * t3 * grad_3d(generator.perm[ii + 1 + generator.perm[jj + 1 + generator.perm[kk + + 1]]], x3, y3, z3) } // scale the return value to [-1, 1] return 32.0 * (n0 + n1 + n2 + n3) } -pub fn simplex_4d(x f64, y f64, z f64, w f64) f64 { +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 @@ -346,8 +347,8 @@ pub fn simplex_4d(x f64, y f64, z f64, w f64) f64 { n0 = 0.0 } else { t0 *= t0 - n0 = t0 * t0 * grad_4d(permutations[ii + permutations[jj + permutations[kk + - permutations[ll]]]], x0, y0, z0, w0) + 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 @@ -356,8 +357,8 @@ pub fn simplex_4d(x f64, y f64, z f64, w f64) f64 { n1 = 0.0 } else { t1 *= t1 - n1 = t1 * t1 * grad_4d(permutations[ii + i1 + permutations[jj + j1 + permutations[kk + k1 + - permutations[ll + l1]]]], x1, y1, z1, w1) + 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 @@ -366,8 +367,8 @@ pub fn simplex_4d(x f64, y f64, z f64, w f64) f64 { n2 = 0.0 } else { t2 *= t2 - n2 = t2 * t2 * grad_4d(permutations[ii + i2 + permutations[jj + j2 + permutations[kk + k2 + - permutations[ll + l2]]]], x2, y2, z2, w2) + 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 @@ -376,8 +377,8 @@ pub fn simplex_4d(x f64, y f64, z f64, w f64) f64 { n3 = 0.0 } else { t3 *= t3 - n3 = t3 * t3 * grad_4d(permutations[ii + i3 + permutations[jj + j3 + permutations[kk + k3 + - permutations[ll + l3]]]], x3, y3, z3, w3) + 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 @@ -386,8 +387,8 @@ pub fn simplex_4d(x f64, y f64, z f64, w f64) f64 { n4 = 0.0 } else { t4 *= t4 - n4 = t4 * t4 * grad_4d(permutations[ii + 1 + permutations[jj + 1 + permutations[kk + 1 + - permutations[ll + 1]]]], x4, y4, z4, w4) + 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) +} From d6d226f7fb916dddbec1c94ff1f4e68d847bc88b Mon Sep 17 00:00:00 2001 From: PottierLoic Date: Sat, 13 Jul 2024 14:18:03 +0200 Subject: [PATCH 06/11] noise: add comments --- noise/simplex.v | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/noise/simplex.v b/noise/simplex.v index 000466bd3..176fe40a6 100644 --- a/noise/simplex.v +++ b/noise/simplex.v @@ -2,13 +2,13 @@ module noise import math -// skewing factors for 2d case +// 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 +// skewing factors for 3D case const f3 = f64(1.0 / 3.0) const g3 = f64(1.0 / 6.0) -// skewing factors for 4d case +// 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) @@ -25,6 +25,7 @@ const simplex := [ ] // 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) @@ -32,6 +33,7 @@ fn grad_1d(hash int, x f64) f64 { 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 } @@ -47,6 +49,7 @@ fn grad_2d(hash int, x f64, y f64) f64 { }) } +// 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 } @@ -66,6 +69,7 @@ fn grad_3d(hash int, x f64, y f64, z f64) f64 { }) } +// 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 } @@ -86,6 +90,7 @@ fn grad_4d(hash int, x f64, y f64, z f64, t f64) f64 { }) } +// 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 @@ -100,27 +105,22 @@ pub fn (generator Generator) simplex_1d(x f64) f64 { t1 *= t1 n1 := t1 * t1 * grad_1d(generator.perm[i1 & 0xff], x1) - // we scale it to [-1, 1] 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 { - // skew the input space to determine which simplex cell we're in s := (x + y) * noise.f2 i := int(x + s) j := int(y + s) - // unskew the cell origin back to x, y space t := f64(i + j) * noise.g2 - // distances from the cell origin x0 := x - (i - t) y0 := y - (j - t) i1, j1 := if x0 > y0 { - // lower triangle 1, 0 } else { - // upper triangle 0, 1 } @@ -129,11 +129,9 @@ pub fn (generator Generator) simplex_2d(x f64, y f64) f64 { x2 := x0 - 1.0 + noise.g2 * 2.0 y2 := y0 - 1.0 + noise.g2 * 2.0 - // avoid oob ii := i & 0xff jj := j & 0xff - // calculate the 3 corners mut t0 := 0.5 - x0 * x0 - y0 * y0 mut n0 := 0.0 if t0 < 0 { @@ -162,12 +160,11 @@ pub fn (generator Generator) simplex_2d(x f64, y f64) f64 { n2 = t2 * t2 * grad_2d(generator.perm[ii + 1 + generator.perm[jj + 1]], x2, y2) } - // scale the return value to [-1, 1] 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 { - // skew the input space to determine which simplex cell we're in s := (x + y + z) * noise.f3 xs := x + s ys := y + s @@ -176,9 +173,7 @@ pub fn (generator Generator) simplex_3d(x f64, y f64, z f64) f64 { j := int(ys) k := int(zs) - // unskew the cell origin back to x, y, z space t := f64(i + j + k) * noise.g3 - // distances from cell origin x0 := x - (i - t) y0 := y - (j - t) z0 := z - (k - t) @@ -220,7 +215,6 @@ pub fn (generator Generator) simplex_3d(x f64, y f64, z f64) f64 { } } - // offsets for corners in x, y, z coords x1 := x0 - i1 + noise.g3 y1 := y0 - j1 + noise.g3 z1 := z0 - k1 + noise.g3 @@ -275,10 +269,10 @@ pub fn (generator Generator) simplex_3d(x f64, y f64, z f64) f64 { 1]]], x3, y3, z3) } - // scale the return value to [-1, 1] 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 From c8f94bf167589b27defc478c7951985415e76e0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Pottier?= Date: Tue, 23 Jul 2024 13:00:44 +0200 Subject: [PATCH 07/11] noise: examples --- examples/noise_simplex_2d/README.md | 16 ++++++++++++ examples/noise_simplex_2d/main.v | 38 +++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 examples/noise_simplex_2d/README.md create mode 100644 examples/noise_simplex_2d/main.v diff --git a/examples/noise_simplex_2d/README.md b/examples/noise_simplex_2d/README.md new file mode 100644 index 000000000..dde860487 --- /dev/null +++ b/examples/noise_simplex_2d/README.md @@ -0,0 +1,16 @@ +# Example - plot_bar 📘 + +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..4a1985153 --- /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{cap: 1600} + mut y := []f64{cap: 1600} + mut z := []f64{cap: 1600} + + 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()! +} From 53c91c0167c742f0f0484d1c8046cbd8646ce40e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Pottier?= Date: Tue, 23 Jul 2024 15:12:41 +0200 Subject: [PATCH 08/11] noise: add fractal noise example --- examples/noise_fractal_2d/README.md | 16 +++++++++ examples/noise_fractal_2d/main.v | 54 +++++++++++++++++++++++++++++ examples/noise_simplex_2d/main.v | 6 ++-- 3 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 examples/noise_fractal_2d/README.md create mode 100644 examples/noise_fractal_2d/main.v diff --git a/examples/noise_fractal_2d/README.md b/examples/noise_fractal_2d/README.md new file mode 100644 index 000000000..8de9f2210 --- /dev/null +++ b/examples/noise_fractal_2d/README.md @@ -0,0 +1,16 @@ +# Example - plot_bar 📘 + +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..a5dd8e2bf --- /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/main.v b/examples/noise_simplex_2d/main.v index 4a1985153..031441cb3 100644 --- a/examples/noise_simplex_2d/main.v +++ b/examples/noise_simplex_2d/main.v @@ -11,9 +11,9 @@ fn main() { mut generator := noise.Generator.new() generator.randomize() - mut x := []f64{cap: 1600} - mut y := []f64{cap: 1600} - mut z := []f64{cap: 1600} + mut x := []f64{} + mut y := []f64{} + mut z := []f64{} for xx in 0 .. 40 { for yy in 0 .. 40 { From 4861581dc194df819be957521e0155aacbf6333f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Pottier?= Date: Tue, 23 Jul 2024 15:14:57 +0200 Subject: [PATCH 09/11] noise: fmt --- examples/noise_fractal_2d/main.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/noise_fractal_2d/main.v b/examples/noise_fractal_2d/main.v index a5dd8e2bf..a5ef30d25 100644 --- a/examples/noise_fractal_2d/main.v +++ b/examples/noise_fractal_2d/main.v @@ -15,8 +15,8 @@ fn main() { mut y := []f64{} mut z := []f64{} - // 5 layers of simplex noise - octaves := 5 + // 5 layers of simplex noise + octaves := 5 persistence := 0.5 for xx in 0 .. 200 { @@ -26,7 +26,7 @@ fn main() { mut amplitude := 1.0 mut max_value := 0.0 - for _ in 0..octaves { + for _ in 0 .. octaves { total += generator.simplex_2d(0.03 * xx * frequency, 0.03 * yy * frequency) * amplitude max_value += amplitude amplitude *= persistence From f918cdf59ea9bdadc14529873dc177d6089e374c Mon Sep 17 00:00:00 2001 From: Ulises Jeremias Date: Sun, 4 Aug 2024 21:48:01 -0300 Subject: [PATCH 10/11] Update README.md --- examples/noise_fractal_2d/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/noise_fractal_2d/README.md b/examples/noise_fractal_2d/README.md index 8de9f2210..ea94dd58f 100644 --- a/examples/noise_fractal_2d/README.md +++ b/examples/noise_fractal_2d/README.md @@ -1,4 +1,4 @@ -# Example - plot_bar 📘 +# Example - noise_fractal_2d 📘 This example demonstrates the usage of the V Scientific Library for generating pink noise. From 80d461c0026d2a8acd75982441f501e457f226bd Mon Sep 17 00:00:00 2001 From: Ulises Jeremias Date: Sun, 4 Aug 2024 21:48:24 -0300 Subject: [PATCH 11/11] Update README.md --- examples/noise_simplex_2d/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/noise_simplex_2d/README.md b/examples/noise_simplex_2d/README.md index dde860487..f21dc9268 100644 --- a/examples/noise_simplex_2d/README.md +++ b/examples/noise_simplex_2d/README.md @@ -1,4 +1,4 @@ -# Example - plot_bar 📘 +# Example - noise_simple_2d 📘 This example demonstrates the usage of the V Scientific Library for generating simplex noise.