fixed lake and river merging
This commit is contained in:
@@ -100,10 +100,16 @@ func main() {
|
||||
if canvasImg.Image == nil || heightmapImg.Image == nil {
|
||||
// Initial image generation
|
||||
noiseImg := GenerateHeightmap(settings.Width, settings.Height, int(settings.Detail), 100.0, settings.Seed)
|
||||
lakeImage, lakePixels := GenerateLakes(settings.Width, settings.Height, settings.Lakes, settings.LakeSizeLower, settings.LakeSizeUpper, noiseImg, settings.Seed)
|
||||
riverImage, riverPixels := GenerateRivers(settings.Width, settings.Height, settings.Rivers, settings.MinRiverWidth, settings.MaxRiverWidth, settings.RiverCurvyness, lakeImage, lakePixels, settings.Seed)
|
||||
lakeImage, lakes := GenerateLakes(settings.Width, settings.Height, settings.Lakes, settings.LakeSizeLower, settings.LakeSizeUpper, noiseImg, settings.Seed)
|
||||
riverImage, riverPixels := GenerateRivers(settings.Width, settings.Height, settings.Rivers, settings.MinRiverWidth, settings.MaxRiverWidth, settings.RiverCurvyness, lakeImage, lakes, settings.Seed)
|
||||
finalImage := riverImage.(*image.RGBA)
|
||||
allWaterPixels := append(lakePixels, riverPixels...)
|
||||
|
||||
var flatLakePixels []image.Point
|
||||
for _, lake := range lakes {
|
||||
flatLakePixels = append(flatLakePixels, lake...)
|
||||
}
|
||||
allWaterPixels := append(flatLakePixels, riverPixels...)
|
||||
|
||||
GenerateTrees(finalImage, allWaterPixels, settings.MinTreeSize, settings.MaxTreeSize, settings.TreeCoverage, settings.TreeClumpiness, settings.Seed)
|
||||
darkenedHeightmap := DarkenLakeAreas(noiseImg, allWaterPixels)
|
||||
compositeImg := ApplyRoughness(darkenedHeightmap, settings.Roughness)
|
||||
@@ -267,16 +273,20 @@ func main() {
|
||||
currentStep++
|
||||
progressBar.SetText(fmt.Sprintf("Step %d/%d: Generating Lakes", currentStep, steps))
|
||||
progressBar.SetValue(float64(currentStep) / float64(steps))
|
||||
lakeImage, lakePixels := GenerateLakes(settings.Width, settings.Height, settings.Lakes, settings.LakeSizeLower, settings.LakeSizeUpper, noiseImg, settings.Seed)
|
||||
lakeImage, lakes := GenerateLakes(settings.Width, settings.Height, settings.Lakes, settings.LakeSizeLower, settings.LakeSizeUpper, noiseImg, settings.Seed)
|
||||
|
||||
// Step 3: Generating Rivers
|
||||
currentStep++
|
||||
progressBar.SetText(fmt.Sprintf("Step %d/%d: Generating Rivers", currentStep, steps))
|
||||
progressBar.SetValue(float64(currentStep) / float64(steps))
|
||||
riverImage, riverPixels := GenerateRivers(settings.Width, settings.Height, settings.Rivers, settings.MinRiverWidth, settings.MaxRiverWidth, settings.RiverCurvyness, lakeImage, lakePixels, settings.Seed)
|
||||
riverImage, riverPixels := GenerateRivers(settings.Width, settings.Height, settings.Rivers, settings.MinRiverWidth, settings.MaxRiverWidth, settings.RiverCurvyness, lakeImage, lakes, settings.Seed)
|
||||
|
||||
finalImage := riverImage.(*image.RGBA)
|
||||
allWaterPixels := append(lakePixels, riverPixels...)
|
||||
var flatLakePixels []image.Point
|
||||
for _, lake := range lakes {
|
||||
flatLakePixels = append(flatLakePixels, lake...)
|
||||
}
|
||||
allWaterPixels := append(flatLakePixels, riverPixels...)
|
||||
|
||||
// Step 4: Darkening Water Areas
|
||||
currentStep++
|
||||
|
||||
+40
-9
@@ -45,8 +45,7 @@ func (pq *priorityQueue) Pop() interface{} {
|
||||
return item
|
||||
}
|
||||
|
||||
// GenerateLakes creates a specific number of lakes by dividing the image into chunks and placing one lake per chunk.
|
||||
func GenerateLakes(width, height, numLakes int, lakeSizeLower, lakeSizeUpper float64, heightmap image.Image, seed int64) (image.Image, []image.Point) {
|
||||
func GenerateLakes(width, height, numLakes int, lakeSizeLower, lakeSizeUpper float64, heightmap image.Image, seed int64) (image.Image, [][]image.Point) {
|
||||
canvas := image.NewRGBA(image.Rect(0, 0, width, height))
|
||||
draw.Draw(canvas, canvas.Bounds(), image.NewUniform(color.White), image.Point{}, draw.Src)
|
||||
|
||||
@@ -54,7 +53,7 @@ func GenerateLakes(width, height, numLakes int, lakeSizeLower, lakeSizeUpper flo
|
||||
return canvas, nil
|
||||
}
|
||||
|
||||
var allLakePixels []image.Point
|
||||
var allLakes [][]image.Point
|
||||
randSrc := rand.New(rand.NewSource(seed))
|
||||
|
||||
// 1. Divide the image into a grid
|
||||
@@ -86,6 +85,8 @@ func GenerateLakes(width, height, numLakes int, lakeSizeLower, lakeSizeUpper flo
|
||||
break
|
||||
}
|
||||
|
||||
var currentLake []image.Point
|
||||
|
||||
// Each lake gets a random size within the defined range
|
||||
lakeSize := lakeSizeLower
|
||||
if lakeSizeUpper > lakeSizeLower {
|
||||
@@ -147,7 +148,7 @@ func GenerateLakes(width, height, numLakes int, lakeSizeLower, lakeSizeUpper flo
|
||||
|
||||
// The pixel is valid, claim it.
|
||||
canvas.Set(current.point.X, current.point.Y, color.RGBA{R: 0, G: 0, B: 255, A: 255})
|
||||
allLakePixels = append(allLakePixels, current.point)
|
||||
currentLake = append(currentLake, current.point)
|
||||
lakeCount++
|
||||
|
||||
// Add neighbors, constrained to the chunk rectangle
|
||||
@@ -170,9 +171,12 @@ func GenerateLakes(width, height, numLakes int, lakeSizeLower, lakeSizeUpper flo
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(currentLake) > 0 {
|
||||
allLakes = append(allLakes, currentLake)
|
||||
}
|
||||
}
|
||||
|
||||
return canvas, allLakePixels
|
||||
return canvas, allLakes
|
||||
}
|
||||
|
||||
type River struct {
|
||||
@@ -181,7 +185,7 @@ type River struct {
|
||||
Points []image.Point
|
||||
}
|
||||
|
||||
func GenerateRivers(width, height, numRivers int, minWidth, maxWidth, curvyness float64, inputImage image.Image, lakePixels []image.Point, seed int64) (image.Image, []image.Point) {
|
||||
func GenerateRivers(width, height, numRivers int, minWidth, maxWidth, curvyness float64, inputImage image.Image, lakes [][]image.Point, seed int64) (image.Image, []image.Point) {
|
||||
if numRivers == 0 {
|
||||
return inputImage, nil
|
||||
}
|
||||
@@ -197,8 +201,12 @@ func GenerateRivers(width, height, numRivers int, minWidth, maxWidth, curvyness
|
||||
avgDim := float64(width+height) / 2.0
|
||||
|
||||
isWater := make(map[image.Point]bool)
|
||||
for _, p := range lakePixels {
|
||||
isWater[p] = true
|
||||
lakePixelMap := make(map[image.Point]int)
|
||||
for i, lake := range lakes {
|
||||
for _, p := range lake {
|
||||
isWater[p] = true
|
||||
lakePixelMap[p] = i
|
||||
}
|
||||
}
|
||||
|
||||
rivers := make([]River, numRivers)
|
||||
@@ -232,7 +240,14 @@ func GenerateRivers(width, height, numRivers int, minWidth, maxWidth, curvyness
|
||||
|
||||
for _, p := range path {
|
||||
if isWater[p] {
|
||||
r.End = p
|
||||
if lakeIndex, isLake := lakePixelMap[p]; isLake {
|
||||
// Intersection is with a lake, find its center
|
||||
lakeCenter := findCenter(lakes[lakeIndex])
|
||||
r.End = lakeCenter
|
||||
} else {
|
||||
// Intersection is with another river
|
||||
r.End = p
|
||||
}
|
||||
path = calculatePath(r.Start, r.End, curvyness/100.0, avgDim, randSrc, numControlPoints)
|
||||
break
|
||||
}
|
||||
@@ -242,6 +257,7 @@ func GenerateRivers(width, height, numRivers int, minWidth, maxWidth, curvyness
|
||||
radius := riverWidthPx / 2.0
|
||||
|
||||
for _, p := range path {
|
||||
// When drawing river pixels, add them to isWater to detect river-river intersections
|
||||
drawCircle(canvas, p, radius, color.RGBA{R: 0, G: 0, B: 255, A: 255}, &allRiverPixels, isWater)
|
||||
}
|
||||
r.Points = path
|
||||
@@ -250,6 +266,21 @@ func GenerateRivers(width, height, numRivers int, minWidth, maxWidth, curvyness
|
||||
return canvas, allRiverPixels
|
||||
}
|
||||
|
||||
func findCenter(pixels []image.Point) image.Point {
|
||||
if len(pixels) == 0 {
|
||||
return image.Point{}
|
||||
}
|
||||
var sumX, sumY int
|
||||
for _, p := range pixels {
|
||||
sumX += p.X
|
||||
sumY += p.Y
|
||||
}
|
||||
return image.Point{
|
||||
X: sumX / len(pixels),
|
||||
Y: sumY / len(pixels),
|
||||
}
|
||||
}
|
||||
|
||||
func getPointOnEdge(width, height, edge int, randSrc *rand.Rand) image.Point {
|
||||
switch edge {
|
||||
case 0: // Top
|
||||
|
||||
Reference in New Issue
Block a user