Skip to content

Commit

Permalink
noise: implement 2d perlin noise (#42) (#87)
Browse files Browse the repository at this point in the history
  • Loading branch information
boonsboos authored Jun 28, 2022
1 parent f2972f5 commit 3655c92
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 2 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ jobs:

- name: Validate Docs
run: |
cd ./vsl
v check-md .
cd ~
v check-md ~/.vmodules/vsl
ci:
runs-on: ${{ matrix.os }}
Expand Down
69 changes: 69 additions & 0 deletions noise/perlin.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
module noise

import math
import rand

// implemented according to the example implementation on wikipedia
// https://en.wikipedia.org/wiki/Perlin_noise#Implementation

struct Vec2 {
x f32
y f32
}

[inline]
fn random_gradient() ?Vec2 {
nr := rand.f32_in_range(0.0, math.pi * 2)?
return Vec2{
x: math.cosf(nr)
y: math.sinf(nr)
}
}

[inline]
fn interpolate(a f32, b f32, w f32) f32 {
return ((a - b) * w) + a
}

[inline]
fn dot(ix int, iy int, x f32, y f32) ?f32 {
vec := random_gradient()?
dx := x - f32(ix)
dy := y - f32(iy)
return dx * vec.x + dy * vec.y
}

// gets the noise value at coordinate (x, y)
[inline]
pub fn perlin(x f32, y f32) ?f32 {
x1 := int(math.floor(x))
y1 := int(math.floor(y))
x2 := x1 + 1
y2 := y1 + 1

sx := x - f32(x1)
sy := y - f32(y2)

n0 := dot(x1, y1, x, y)?
n1 := dot(x2, y1, x, y)?
first := interpolate(n0, n1, sx)

n2 := dot(x1, y2, x, y)?
n3 := dot(x2, y2, x, y)?
second := interpolate(n2, n3, sx)

return interpolate(first, second, sy)
}

// creates a 2d array of perlin noise of size `w` times `h`
pub fn perlin_many(w int, h int) ?[][]f32 {
mut res := [][]f32{len: h, init: []f32{len: w}}
for i, a in res {
for j, _ in a {
val := perlin(j, i)?
println(f64(val))
res[i][j] = val
}
}
return res
}
16 changes: 16 additions & 0 deletions noise/perlin_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module noise

import rand

fn test_perlin() {
rand.seed([u32(1), 0])
assert perlin(0.0, 0.0) or { assert false } == -0.6457864046096802
}

fn test_perlin_many() {
rand.seed([u32(1), 0])
assert perlin_many(2, 2) or { assert false } == [
[f32(-0.6457864046096802), 0.0279612485319376],
[f32(0.2286834865808487), -0.5146363377571106],
]
}
18 changes: 18 additions & 0 deletions noise/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# noise

This module aims to to implement noise algorithms.

It uses the `rand` module in vlib to generate random numbers,
so you may seed the generator as you see fit.

Example:
```v
import vsl.noise
import rand
fn main() {
rand.seed([u32(1), 0])
println(noise.perlin(0.0, 0.0)?)
}
```
Output: `-0.6457864`

0 comments on commit 3655c92

Please sign in to comment.