119 lines
1.8 KiB
Go
119 lines
1.8 KiB
Go
package utils
|
|
|
|
import (
|
|
"math"
|
|
"math/rand"
|
|
)
|
|
|
|
const (
|
|
B = 0x100
|
|
N = 0x1000
|
|
BM = 0xff
|
|
)
|
|
|
|
func NewPerlin(alpha, beta float64, n int, seed int64) *Perlin {
|
|
return NewPerlinRandSource(alpha, beta, n, rand.NewSource(seed))
|
|
}
|
|
|
|
// Perlin is the noise generator
|
|
type Perlin struct {
|
|
alpha float64
|
|
beta float64
|
|
n int
|
|
|
|
p [B + B + 2]int
|
|
g3 [B + B + 2][3]float64
|
|
g2 [B + B + 2][2]float64
|
|
g1 [B + B + 2]float64
|
|
}
|
|
|
|
func NewPerlinRandSource(alpha, beta float64, n int, source rand.Source) *Perlin {
|
|
var p Perlin
|
|
var i int
|
|
|
|
p.alpha = alpha
|
|
p.beta = beta
|
|
p.n = n
|
|
|
|
r := rand.New(source)
|
|
|
|
for i = 0; i < B; i++ {
|
|
p.p[i] = i
|
|
p.g1[i] = float64((r.Int()%(B+B))-B) / B
|
|
|
|
for j := 0; j < 2; j++ {
|
|
p.g2[i][j] = float64((r.Int()%(B+B))-B) / B
|
|
}
|
|
|
|
normalize2(&p.g2[i])
|
|
}
|
|
|
|
for ; i > 0; i-- {
|
|
k := p.p[i]
|
|
j := r.Int() % B
|
|
p.p[i] = p.p[j]
|
|
p.p[j] = k
|
|
}
|
|
|
|
for i := 0; i < B+2; i++ {
|
|
p.p[B+i] = p.p[i]
|
|
p.g1[B+i] = p.g1[i]
|
|
for j := 0; j < 2; j++ {
|
|
p.g2[B+i][j] = p.g2[i][j]
|
|
}
|
|
for j := 0; j < 3; j++ {
|
|
p.g3[B+i][j] = p.g3[i][j]
|
|
}
|
|
}
|
|
|
|
return &p
|
|
}
|
|
|
|
func normalize2(v *[2]float64) {
|
|
s := math.Sqrt(v[0]*v[0] + v[1]*v[1])
|
|
v[0] = v[0] / s
|
|
v[1] = v[1] / s
|
|
}
|
|
|
|
func (p *Perlin) Noise1D(x float64) float64 {
|
|
var scale float64 = 1
|
|
var sum float64
|
|
px := x
|
|
|
|
for i := 0; i < p.n; i++ {
|
|
val := p.noise1(px)
|
|
sum += val / scale
|
|
scale *= p.alpha
|
|
px *= p.beta
|
|
}
|
|
if sum < 0 {
|
|
sum = sum * -1
|
|
}
|
|
return sum
|
|
}
|
|
|
|
func (p *Perlin) noise1(arg float64) float64 {
|
|
var vec [1]float64
|
|
vec[0] = arg
|
|
|
|
t := vec[0] + N
|
|
bx0 := int(t) & BM
|
|
bx1 := (bx0 + 1) & BM
|
|
rx0 := t - float64(int(t))
|
|
rx1 := rx0 - 1.
|
|
|
|
sx := sCurve(rx0)
|
|
u := rx0 * p.g1[p.p[bx0]]
|
|
v := rx1 * p.g1[p.p[bx1]]
|
|
|
|
return lerp(sx, u, v)
|
|
}
|
|
|
|
func sCurve(t float64) float64 {
|
|
return t * t * (3. - 2.*t)
|
|
}
|
|
|
|
func lerp(t, a, b float64) float64 {
|
|
return a + t*(b-a)
|
|
}
|