gl01/internal/world/worldgen/worldgen.go
2022-02-25 21:33:51 +08:00

106 lines
2.4 KiB
Go

package worldgen
import (
"sync"
packworld "edgaru089.ml/go/gl01/internal/world"
"edgaru089.ml/go/gl01/internal/world/blocks"
"github.com/aquilax/go-perlin"
)
const (
Alpha = 5 // Weight forming the noise sum
Beta = 2 // harmonic scaling/spacing
N = 3 // iterations
AltitudeDensity = 20 // Density of the noise in altitude
Sealevel = 63 // Space with Y=63 and lower should be the sea
Highest = 74 // Highest part of the terrain
Lowest = 54 // Lowest part of the terrain
)
var perlins map[int64]*perlin.Perlin
var perlinsLock sync.RWMutex
func init() {
perlins = make(map[int64]*perlin.Perlin)
}
func fractal(p *perlin.Perlin, x, y float64, levels int) float64 {
ans := 0.0
amp := 1.0
for i := 0; i < levels; i++ {
ans += amp * p.Noise2D(x, y)
amp /= 3
x *= 2
y *= 2
}
return ans
}
// Chunk generates the chunk (must with chunkID set!!) with seed.
func Chunk(chunk *packworld.Chunk, world *packworld.World, seed int64) {
perlinsLock.RLock()
p, ok := perlins[seed]
if !ok {
perlinsLock.RUnlock()
perlinsLock.Lock()
p = perlin.NewPerlin(Alpha, Beta, N, seed)
perlins[seed] = p
perlinsLock.Unlock()
} else {
perlinsLock.RUnlock()
}
//log.Printf("noise=%.5f", p.Noise2D(0.1, 0.1))
offX := packworld.ChunkSizeX * chunk.X
offZ := packworld.ChunkSizeZ * chunk.Z
for x := 0; x < packworld.ChunkSizeX; x++ {
for z := 0; z < packworld.ChunkSizeZ; z++ {
height := Lowest + int(float64(Highest-Lowest)*(fractal(
p,
float64(offX+x)/AltitudeDensity,
float64(offZ+z)/AltitudeDensity, 6)/2+0.5))
//log.Printf("height = %d (noise=%.5f)", height, p.Noise2D(float64(offX+x)/AltitudeDensity, float64(offZ+z)/AltitudeDensity)/2+0.5)
// water
for y := Sealevel; y > height; y-- {
chunk.Id[x][y][z] = blocks.Water
}
// covering dirt
if height >= Sealevel {
chunk.Id[x][height][z] = blocks.Grass
} else {
chunk.Id[x][height][z] = blocks.Dirt
}
//chunk.Id[x][height][z] = blocks.DebugDir
chunk.Id[x][height-1][z] = blocks.Dirt
chunk.Id[x][height-2][z] = blocks.Dirt
chunk.Id[x][height-3][z] = blocks.Dirt
height -= 4
// stone in the middle
for y := height; y >= 1; y-- {
chunk.Id[x][y][z] = blocks.Stone
}
// bedrock at the bottom
chunk.Id[x][0][z] = blocks.Bedrock
// plant trees
if height >= 50 && height <= 70 {
if p.Noise2D(float64(offX+x), float64(offZ+z)) > 0.9 {
}
}
}
}
chunk.InvalidateRender()
}