Add smooth terrain

This commit is contained in:
2024-06-16 20:08:24 +02:00
parent 7c59b04ec3
commit c1aa61ca95
22 changed files with 71 additions and 11 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 B

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 B

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 844 B

After

Width:  |  Height:  |  Size: 809 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 960 B

After

Width:  |  Height:  |  Size: 888 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 B

After

Width:  |  Height:  |  Size: 748 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 B

After

Width:  |  Height:  |  Size: 658 B

View File

@@ -105,7 +105,7 @@ def filter_sobel(image: Union[str, Image]) -> Image:
return image
def filter_smooth(image: Union[str, Image], radius: int = 3):
def filter_smooth_theshold(image: Union[str, Image], radius: int = 3):
"""
:param image: white and black image representing the derivative of the terrain (sobel), where black is flat and white is very steep.
:param radius: Radius of the Gaussian blur.
@@ -135,6 +135,14 @@ def filter_smooth(image: Union[str, Image], radius: int = 3):
return Image.fromarray(bool_array)
def filter_smooth(image: Union[str, Image], radius: int = 3):
image = handle_import_image(image)
image = image.convert('L')
image = image.filter(ImageFilter.GaussianBlur(radius))
return image
def subtract_map(image: Union[str, Image], substractImage: Union[str, Image]) -> Image:
image = handle_import_image(image)
substractImage = handle_import_image(substractImage).convert('L')
@@ -163,7 +171,7 @@ def group_map(image1: Union[str, Image], image2: Union[str, Image]) -> Image:
def filter_smooth_array(array: np.ndarray, radius: int = 3) -> np.ndarray:
image = Image.fromarray(array)
smooth_image = filter_smooth(image, radius)
smooth_image = filter_smooth_theshold(image, radius)
array = np.array(smooth_image)
return array
@@ -182,7 +190,7 @@ def filter_remove_details(image: Union[str, Image], n: int = 20) -> Image:
def highway_map() -> Image:
print("[Data Analysis] Generating highway map...")
smooth_sobel = filter_smooth("./world_maker/data/sobelmap.png", 1)
smooth_sobel = filter_smooth_theshold("./world_maker/data/sobelmap.png", 1)
negative_smooth_sobel = filter_negative(smooth_sobel)
negative_smooth_sobel_water = subtract_map(
negative_smooth_sobel, './world_maker/data/watermap.png')
@@ -247,7 +255,7 @@ def smooth_sobel_water() -> Image:
watermap = filter_negative(
filter_remove_details(filter_negative(watermap), 5))
sobel = handle_import_image("./world_maker/data/sobelmap.png")
sobel = filter_remove_details(filter_smooth(sobel, 1), 2)
sobel = filter_remove_details(filter_smooth_theshold(sobel, 1), 2)
group = group_map(watermap, sobel)
group = filter_negative(group)
group.save('./world_maker/data/smooth_sobel_watermap.png')

View File

@@ -1,14 +1,14 @@
from typing import Union
import numpy as np
from gdpc import Editor, Block, geometry
from gdpc import Editor, Block, geometry, lookup
from PIL import Image
from skimage import morphology
from world_maker.data_analysis import handle_import_image
def remove_trees(heightmap: Union[str, Image], treesmap: Union[str, Image], mask: Union[str, Image], ):
def remove_trees(heightmap: Union[str, Image], treesmap: Union[str, Image], mask: Union[str, Image]):
editor = Editor(buffering=True)
build_area = editor.getBuildArea()
@@ -29,7 +29,7 @@ def remove_trees(heightmap: Union[str, Image], treesmap: Union[str, Image], mask
for x in range(0, distance[0]):
for z in range(0, distance[1]):
if mask.getpixel((x, z)) == 255 and treesmap.getpixel((x, z)) > 0 and (x, z) not in removed:
if mask.getpixel((x, z)) != 0 and treesmap.getpixel((x, z)) > 0 and (x, z) not in removed:
treeArea = morphology.flood(treesmap, (z, x), tolerance=1)
blend = Image.blend(Image.fromarray(treeArea).convert(
@@ -52,3 +52,48 @@ def remove_trees(heightmap: Union[str, Image], treesmap: Union[str, Image], mask
y_top = removed_treesmap.getpixel((x, z))
geometry.placeLine(
editor, (start[0] + x, y+1, start[1] + z), (start[0] + x, y_top, start[1] + z), Block('air'))
def smooth_terrain(heightmap: Union[str, Image], heightmap_smooth: Union[str, Image], mask: Union[str, Image]):
editor = Editor()
build_area = editor.getBuildArea()
build_rectangle = build_area.toRect()
start = build_rectangle.begin
distance = (max(build_rectangle.end[0], build_rectangle.begin[0]) - min(build_rectangle.end[0], build_rectangle.begin[0]), max(
build_rectangle.end[1], build_rectangle.begin[1]) - min(build_rectangle.end[1], build_rectangle.begin[1]))
heightmap = handle_import_image(heightmap).convert('L')
heightmap_smooth = handle_import_image(heightmap_smooth).convert('L')
mask = handle_import_image(mask).convert('L')
smooth_terrain_delta = Image.new("RGB", distance, 0)
slice = editor.loadWorldSlice(build_rectangle)
smoothable_blocks = lookup.OVERWORLD_SOILS | lookup.OVERWORLD_STONES | lookup.SNOWS
for x in range(0, distance[0]):
for z in range(0, distance[1]):
if mask.getpixel((x, z)) != 0:
y = heightmap.getpixel((x, z))
y_smooth = heightmap_smooth.getpixel((x, z))
delta = y - y_smooth
smooth_terrain_delta.putpixel((x, z), delta)
if delta != 0:
block = slice.getBlock((x, y, z))
if block.id in smoothable_blocks:
if delta > 0:
geometry.placeLine(
editor, (start[0] + x, y, start[1] + z), (start[0] + x, y_smooth, start[1] + z), Block('air'))
editor.placeBlock(
(start[0] + x, y_smooth, start[1] + z), block)
else:
geometry.placeLine(
editor, (start[0] + x, y, start[1] + z), (start[0] + x, y_smooth, start[1] + z), block)
smooth_terrain_delta.save('./world_maker/data/smooth_terrain_delta.png')

View File

@@ -1,7 +1,7 @@
from world_maker.World import World
from PIL import Image
from world_maker.data_analysis import (get_data, filter_negative, rectangle_2D_to_3D, skeleton_mountain_map, highway_map, filter_sobel, skeleton_highway_map,
smooth_sobel_water, subtract_map, detect_mountain)
smooth_sobel_water, subtract_map, detect_mountain, filter_smooth)
from world_maker.City import City
from world_maker.Position import Position
from random import randint
@@ -11,8 +11,13 @@ from world_maker.pack_rectangle import generate_building
def world_maker():
world = World()
heightmap, watermap, treemap = get_data(world)
filter_smooth(
'./world_maker/data/heightmap.png', 4).save('./world_maker/data/heightmap_smooth.png')
filter_sobel(
"./world_maker/data/heightmap.png").save('./world_maker/data/sobelmap.png')
smooth_sobel_water_map = smooth_sobel_water()
skeleton_highway = skeleton_highway_map(highway_map())
city = City()