parallelized multiple parts of the program for increased speed.
This commit is contained in:
+59
-9
@@ -6,6 +6,8 @@ import (
|
||||
"image/draw"
|
||||
"math"
|
||||
"math/rand"
|
||||
"runtime"
|
||||
"sync"
|
||||
|
||||
"github.com/aquilax/go-perlin"
|
||||
"github.com/disintegration/imaging"
|
||||
@@ -26,14 +28,27 @@ func GenerateHeightmap(width, height, octaves int, scale float64, seed int64) im
|
||||
scale = 100.0
|
||||
}
|
||||
|
||||
for x := range width {
|
||||
for y := range height {
|
||||
numGoroutines := runtime.NumCPU()
|
||||
var wg sync.WaitGroup
|
||||
rowsPerGoroutine := height / numGoroutines
|
||||
|
||||
for i := 0; i < numGoroutines; i++ {
|
||||
startY := i * rowsPerGoroutine
|
||||
endY := startY + rowsPerGoroutine
|
||||
if i == numGoroutines-1 {
|
||||
endY = height
|
||||
}
|
||||
wg.Add(1)
|
||||
go func(startY, endY int) {
|
||||
defer wg.Done()
|
||||
for y := startY; y < endY; y++ {
|
||||
for x := 0; x < width; x++ {
|
||||
var noise float64
|
||||
frequency := 1.0
|
||||
amplitude := 1.0
|
||||
maxAmplitude := 0.0
|
||||
|
||||
for range octaves {
|
||||
for j := 0; j < octaves; j++ {
|
||||
noise += p.Noise2D(float64(x)*frequency/scale, float64(y)*frequency/scale) * amplitude
|
||||
maxAmplitude += amplitude
|
||||
amplitude /= 2.0
|
||||
@@ -45,6 +60,9 @@ func GenerateHeightmap(width, height, octaves int, scale float64, seed int64) im
|
||||
img.SetGray(x, y, color.Gray{Y: grayColor})
|
||||
}
|
||||
}
|
||||
}(startY, endY)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
return img
|
||||
}
|
||||
@@ -201,13 +219,36 @@ func GenerateTrees(img *image.RGBA, lakePixels, roadPixels []image.Point, minTre
|
||||
|
||||
var treePixels []image.Point
|
||||
// 5. Draw the trees.
|
||||
for _, p := range allPoints {
|
||||
size := minTreeSize + randSrc.Float64()*(maxTreeSize-minTreeSize)
|
||||
numGoroutines := runtime.NumCPU()
|
||||
if len(allPoints) < numGoroutines {
|
||||
numGoroutines = len(allPoints)
|
||||
}
|
||||
if numGoroutines == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
results := make(chan []image.Point, numGoroutines)
|
||||
pointsPerGoroutine := (len(allPoints) + numGoroutines - 1) / numGoroutines
|
||||
|
||||
for i := 0; i < numGoroutines; i++ {
|
||||
start := i * pointsPerGoroutine
|
||||
end := start + pointsPerGoroutine
|
||||
if end > len(allPoints) {
|
||||
end = len(allPoints)
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func(points []image.Point, seed int64) {
|
||||
defer wg.Done()
|
||||
localRand := rand.New(rand.NewSource(seed))
|
||||
localTreePixels := make([]image.Point, 0)
|
||||
for _, p := range points {
|
||||
size := minTreeSize + localRand.Float64()*(maxTreeSize-minTreeSize)
|
||||
if size <= 0 {
|
||||
continue
|
||||
}
|
||||
r := size / 2
|
||||
// Use a simple pixel-by-pixel circle drawing method
|
||||
for y := p.Y - int(r); y <= p.Y+int(r); y++ {
|
||||
for x := p.X - int(r); x <= p.X+int(r); x++ {
|
||||
pt := image.Point{X: x, Y: y}
|
||||
@@ -216,14 +257,23 @@ func GenerateTrees(img *image.RGBA, lakePixels, roadPixels []image.Point, minTre
|
||||
}
|
||||
|
||||
if (math.Pow(float64(x-p.X), 2) + math.Pow(float64(y-p.Y), 2)) <= r*r {
|
||||
// Blend the tree color with the background
|
||||
// For simplicity, we just set a solid color for now.
|
||||
img.Set(x, y, color.RGBA{R: 0, G: 100, B: 0, A: 255})
|
||||
treePixels = append(treePixels, pt)
|
||||
localTreePixels = append(localTreePixels, pt)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
results <- localTreePixels
|
||||
}(allPoints[start:end], seed+int64(i))
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
close(results)
|
||||
|
||||
for res := range results {
|
||||
treePixels = append(treePixels, res...)
|
||||
}
|
||||
|
||||
return treePixels
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user