add perlin noise
This commit is contained in:
parent
c25daba2ed
commit
eddb3f9709
3 changed files with 115 additions and 15 deletions
100
common/perlinnoise.go
Normal file
100
common/perlinnoise.go
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
perlinYwrapb = 4
|
||||||
|
perlinYwrap = 1 << perlinYwrapb
|
||||||
|
perlinZwrapb = 8
|
||||||
|
perlinZwrap = 1 << perlinZwrapb
|
||||||
|
perlinSize = 4095
|
||||||
|
perlinOctaves = 4
|
||||||
|
perlinAmpFalloff = 0.5
|
||||||
|
)
|
||||||
|
|
||||||
|
type perlinNoise struct {
|
||||||
|
perlin []float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPerlinNoise() *perlinNoise {
|
||||||
|
perlin := &perlinNoise{perlin: nil}
|
||||||
|
perlin.perlin = make([]float64, perlinSize+1)
|
||||||
|
|
||||||
|
for i, _ := range perlin.perlin {
|
||||||
|
perlin.perlin[i] = rand.Float64()
|
||||||
|
}
|
||||||
|
return perlin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *perlinNoise) Noise(x, y, z float64) float64 {
|
||||||
|
if x < 0 {
|
||||||
|
x = -x
|
||||||
|
}
|
||||||
|
|
||||||
|
if y < 0 {
|
||||||
|
y = -y
|
||||||
|
}
|
||||||
|
|
||||||
|
if z < 0 {
|
||||||
|
z = -z
|
||||||
|
}
|
||||||
|
|
||||||
|
xi, yi, zi := int(math.Floor(x)), int(math.Floor(y)), int(math.Floor(z))
|
||||||
|
xf, yf, zf := x-float64(xi), y-float64(yi), z-float64(zi)
|
||||||
|
|
||||||
|
var rxf, ryf, n1, n2, n3 float64
|
||||||
|
var r float64
|
||||||
|
var ampl float64 = 0.5
|
||||||
|
|
||||||
|
for o := 0; o < perlinOctaves; o++ {
|
||||||
|
of := xi + (yi << perlinYwrapb) + (zi << perlinZwrapb)
|
||||||
|
|
||||||
|
rxf = scaledCosin(xf)
|
||||||
|
ryf = scaledCosin(yf)
|
||||||
|
|
||||||
|
n1 = p.perlin[of&perlinSize]
|
||||||
|
n1 += rxf * (p.perlin[(of+1)&perlinSize] - n1)
|
||||||
|
n2 = p.perlin[(of+perlinYwrap)&perlinSize]
|
||||||
|
n2 += rxf * (p.perlin[(of+perlinYwrap+1)&perlinSize] - n2)
|
||||||
|
n1 += ryf * (n2 - n1)
|
||||||
|
|
||||||
|
of += perlinZwrap
|
||||||
|
n2 = p.perlin[of&perlinSize]
|
||||||
|
n2 += rxf * (p.perlin[(of+1)&perlinSize] - n2)
|
||||||
|
n3 = p.perlin[(of+perlinYwrap)&perlinSize]
|
||||||
|
n3 += rxf * (p.perlin[(of+perlinYwrap+1)&perlinSize] - n3)
|
||||||
|
n2 += ryf * (n3 - n2)
|
||||||
|
|
||||||
|
n1 += scaledCosin(zf) * (n2 - n1)
|
||||||
|
|
||||||
|
r += n1 * ampl
|
||||||
|
ampl *= perlinAmpFalloff
|
||||||
|
xi <<= 1
|
||||||
|
xf *= 2
|
||||||
|
yi <<= 1
|
||||||
|
yf *= 2
|
||||||
|
zi <<= 1
|
||||||
|
zf *= 2
|
||||||
|
|
||||||
|
if xf >= 1.0 {
|
||||||
|
xi += 1
|
||||||
|
xf -= 1
|
||||||
|
}
|
||||||
|
if yf >= 1.0 {
|
||||||
|
yi += 1
|
||||||
|
yf -= 1
|
||||||
|
}
|
||||||
|
if zf >= 1.0 {
|
||||||
|
zi += 1
|
||||||
|
zf -= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func scaledCosin(x float64) float64 {
|
||||||
|
return 0.5 * (1.0 - math.Cos(x*math.Pi))
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ type contourLine struct {
|
||||||
lineNum int
|
lineNum int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContourLine(lineNum int) *contourLine{
|
func NewContourLine(lineNum int) *contourLine {
|
||||||
return &contourLine{
|
return &contourLine{
|
||||||
lineNum: lineNum,
|
lineNum: lineNum,
|
||||||
}
|
}
|
||||||
|
@ -22,24 +22,24 @@ func (cl *contourLine) Generative(c *canva) {
|
||||||
ctex := gg.NewContextForRGBA(c.img)
|
ctex := gg.NewContextForRGBA(c.img)
|
||||||
noise := perlin.NewPerlin(2, 2, 3, rand.Int63())
|
noise := perlin.NewPerlin(2, 2, 3, rand.Int63())
|
||||||
|
|
||||||
for i:=0; i<cl.lineNum;i++ {
|
for i := 0; i < cl.lineNum; i++ {
|
||||||
cl := c.opts.colorSchema[rand.Intn(len(c.opts.colorSchema))]
|
cl := c.opts.colorSchema[rand.Intn(len(c.opts.colorSchema))]
|
||||||
|
|
||||||
for j :=0; j<5;j++ {
|
for j := 0; j < 5; j++ {
|
||||||
x := rand.Float64()*float64(c.width)
|
x := rand.Float64() * float64(c.width)
|
||||||
y := rand.Float64()*float64(c.height)
|
y := rand.Float64() * float64(c.height)
|
||||||
|
|
||||||
theta := noise.Noise2D(x/800.0, y/800.0) * math.Pi*2*800
|
theta := noise.Noise2D(x/800.0, y/800.0) * math.Pi * 2 * 800
|
||||||
x += math.Cos(theta)*0.4
|
x += math.Cos(theta) * 0.4
|
||||||
y += math.Sin(theta)*0.4
|
y += math.Sin(theta) * 0.4
|
||||||
|
|
||||||
ctex.SetColor(cl)
|
ctex.SetColor(cl)
|
||||||
ctex.DrawEllipse(x, y, 1, 1)
|
ctex.DrawEllipse(x, y, 1, 1)
|
||||||
ctex.Fill()
|
ctex.Fill()
|
||||||
|
|
||||||
if x > float64(c.width) || x < 0 || y > float64(c.height) || y < 0 || rand.Float64() < 0.001 {
|
if x > float64(c.width) || x < 0 || y > float64(c.height) || y < 0 || rand.Float64() < 0.001 {
|
||||||
x = rand.Float64()*float64(c.width)
|
x = rand.Float64() * float64(c.width)
|
||||||
y = rand.Float64()*float64(c.height)
|
y = rand.Float64() * float64(c.height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,11 @@ import (
|
||||||
func main() {
|
func main() {
|
||||||
rand.Seed(time.Now().Unix())
|
rand.Seed(time.Now().Unix())
|
||||||
colors := []color.RGBA{
|
colors := []color.RGBA{
|
||||||
{0x58, 0x18, 0x45, 0xFF },
|
{0x58, 0x18, 0x45, 0xFF},
|
||||||
{0x90, 0x0C, 0x3F, 0xFF },
|
{0x90, 0x0C, 0x3F, 0xFF},
|
||||||
{0xC7, 0x00, 0x39, 0xFF },
|
{0xC7, 0x00, 0x39, 0xFF},
|
||||||
{0xFF, 0x57, 0x33, 0xFF },
|
{0xFF, 0x57, 0x33, 0xFF},
|
||||||
{0xFF, 0xC3, 0x0F, 0xFF },
|
{0xFF, 0xC3, 0x0F, 0xFF},
|
||||||
}
|
}
|
||||||
c := generativeart.NewCanva(800, 800)
|
c := generativeart.NewCanva(800, 800)
|
||||||
c.SetBackground(color.RGBA{0x1a, 0x06, 0x33, 0xFF})
|
c.SetBackground(color.RGBA{0x1a, 0x06, 0x33, 0xFF})
|
||||||
|
|
Loading…
Reference in a new issue