Skip to content

Commit

Permalink
Mount Gen: convert HeightMap as class. Relates to #1906
Browse files Browse the repository at this point in the history
  • Loading branch information
alek13 committed Jan 6, 2025
1 parent 685b589 commit dde16a6
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 69 deletions.
20 changes: 5 additions & 15 deletions mods/lord/World/mountgen/src/algorithms/cone.lua
Original file line number Diff line number Diff line change
@@ -1,25 +1,15 @@
local math_min, math_max, math_floor, math_ceil, math_sqrt, math_tan, math_rad
= math.min, math.max, math.floor, math.ceil, math.sqrt, math.tan, math.rad

local HeightMap = require('generator.HeightMap')

local MIN_CONE_FOOT_DIAMETER = 3

--- @param diameter number
--- @return number[][]
local function fill_with_zeroes(diameter)
local map = {}
for i = 1, diameter do
map[i] = {}
for j = 1, diameter do map[i][j] = 0 end
end

return map
end
local MIN_CONE_FOOT_DIAMETER = 3

--- Generate mountain as cone
--- @param top_pos Position
--- @param config table
--- @return table, number, number "height map, map size, center_coordinate"
--- @return mountgen.generator.HeightMap, number, number "height map, map size, center_coordinate"
mountgen.cone = function(top_pos, config)
local H = top_pos.y - config.Y0 -- height of truncated cone
local W = 2 * (config.TOP_RADIUS + math_ceil( -- width (diameter) of cone foot
Expand All @@ -32,7 +22,7 @@ mountgen.cone = function(top_pos, config)

local height_map_size = math_min(W, 2 * config.MAX_RADIUS)
local height_map_radius = math_floor(height_map_size / 2)
local height_map = fill_with_zeroes(height_map_size)
local height_map = HeightMap:new(height_map_size)

local l0 = math_sqrt(radius^2 + radius^2)

Expand All @@ -44,7 +34,7 @@ mountgen.cone = function(top_pos, config)
local l = math_sqrt(px^2 + pz^2)
if l <= height_map_radius then
local h = height * (1 - 2 * l / l0)
mountgen.set_value(height_map, z, x, math_min(h, H))
height_map:set_value(z, x, math_min(h, H))
end
end
end
Expand Down
61 changes: 29 additions & 32 deletions mods/lord/World/mountgen/src/algorithms/diamond_square.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
local math_max, math_ceil, math_log, math_random
= math.max, math.ceil, math.log, math.random

local HeightMap = require('generator.HeightMap')


local smooth_filter = {
{ 0, 1, 1, 1, 0 },
Expand All @@ -11,15 +13,15 @@ local smooth_filter = {
}

---smooth map at (x,z)
---@param map table height map
---@param map mountgen.generator.HeightMap height map
---@param z number z coordinate
---@param x number x coordinate
local function smooth(map, z, x)
local sum = 0
local cnt = 0
for i = 1, 5 do
for j = 1, 5 do
local val = mountgen.get_value(map, z - 3 + i, x - 3 + j)
local val = map:get_value(z - 3 + i, x - 3 + j)
if val ~= nil then
cnt = cnt + smooth_filter[i][j]
sum = sum + val * smooth_filter[i][j]
Expand All @@ -29,7 +31,7 @@ local function smooth(map, z, x)
if cnt == 0 then
return
end
mountgen.set_value(map, z, x, sum / cnt)
map:set_value(z, x, sum / cnt)
end

---Random value from -max_value to max_value
Expand Down Expand Up @@ -84,20 +86,14 @@ mountgen.diamond_square = function(map_w, mountain_h, rk_thr, rk_small, rk_big)
n = math_max(n, 1)
local r = 2 ^ (n - 1)
local w = 2 * r + 1
local map = {}
for i = 1, w do
map[i] = {}
for j = 1, w do
map[i][j] = "nan"
end
end
local height_map = HeightMap:new(w)

-- set central peak and corners
mountgen.set_value(map, r, r, H)
mountgen.set_value(map, 0, 0, -H / 2)
mountgen.set_value(map, 0, w - 1, -H / 2)
mountgen.set_value(map, w - 1, 0, -H / 2)
mountgen.set_value(map, w - 1, w - 1, -H / 2)
height_map:set_value(r, r, H)
height_map:set_value(0, 0, -H / 2)
height_map:set_value(0, w - 1, -H / 2)
height_map:set_value(w - 1, 0, -H / 2)
height_map:set_value(w - 1, w - 1, -H / 2)

-- run diamond square
local i = n
Expand All @@ -120,13 +116,13 @@ mountgen.diamond_square = function(map_w, mountain_h, rk_thr, rk_small, rk_big)
for _ = 1, num do
local x = 0
for _ = 1, num do
local val1 = mountgen.get_value(map, z, x)
local val2 = mountgen.get_value(map, z + step, x)
local val3 = mountgen.get_value(map, z, x + step)
local val4 = mountgen.get_value(map, z + step, x + step)
local val1 = height_map:get_value(z, x)
local val2 = height_map:get_value(z + step, x)
local val3 = height_map:get_value(z, x + step)
local val4 = height_map:get_value(z + step, x + step)
local rand = adjust_random(step2 / rk)
local val = average(val1, val2, val3, val4) + rand
mountgen.set_value(map, z + step2, x + step2, val)
height_map:set_value(z + step2, x + step2, val)
x = x + step
end
z = z + step
Expand All @@ -142,20 +138,20 @@ mountgen.diamond_square = function(map_w, mountain_h, rk_thr, rk_small, rk_big)
local rand

rand = adjust_random(step2 / rk)
val1 = mountgen.get_value(map, z - step2, x + step2)
val2 = mountgen.get_value(map, z + step2, x + step2)
val3 = mountgen.get_value(map, z, x)
val4 = mountgen.get_value(map, z, x + step)
val1 = height_map:get_value(z - step2, x + step2)
val2 = height_map:get_value(z + step2, x + step2)
val3 = height_map:get_value(z, x)
val4 = height_map:get_value(z, x + step)
val = average(val1, val2, val3, val4) + rand
mountgen.set_value(map, z, x + step2, val)
height_map:set_value(z, x + step2, val)

rand = adjust_random(step2 / rk)
val1 = mountgen.get_value(map, z + step2, x - step2)
val2 = mountgen.get_value(map, z + step2, x + step2)
val3 = mountgen.get_value(map, z, x)
val4 = mountgen.get_value(map, z + step, x)
val1 = height_map:get_value(z + step2, x - step2)
val2 = height_map:get_value(z + step2, x + step2)
val3 = height_map:get_value(z, x)
val4 = height_map:get_value(z + step, x)
val = average(val1, val2, val3, val4) + rand
mountgen.set_value(map, z + step2, x, val)
height_map:set_value(z + step2, x, val)

x = x + step
end
Expand All @@ -164,6 +160,7 @@ mountgen.diamond_square = function(map_w, mountain_h, rk_thr, rk_small, rk_big)

i = i - 1
end
smooth(map, r, r)
return map, w, r + 1
smooth(height_map, r, r)

return height_map, w, r + 1
end
3 changes: 2 additions & 1 deletion mods/lord/World/mountgen/src/generator.lua
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ mountgen.mountgen = function(top, config)
return
end

--- @type mountgen.generator.HeightMap
local height_map, width, center
if method_name == "cone" then

Expand Down Expand Up @@ -117,7 +118,7 @@ mountgen.mountgen = function(top, config)
if global_z >= 1 and global_z <= width and
global_x >= 1 and global_x <= width and
global_y >= 1 then
local height = math_floor(height_map[global_z][global_x] + 0.5)
local height = math_floor(height_map.map[global_z][global_x] + 0.5)
if height > 0 then
if global_y < height then
data[i] = stone_id
Expand Down
56 changes: 56 additions & 0 deletions mods/lord/World/mountgen/src/generator/HeightMap.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

--- @param size number
--- @return number[][]
local function fill_with_zeroes(size)
local map = {}
for i = 1, size do
map[i] = {}
for j = 1, size do map[i][j] = 0 end
end

return map
end


--- @class mountgen.generator.HeightMap
local HeightMap = {
--- @type number
size = nil,
--- @type number[][]
map = nil,
}

function HeightMap:new(size)
local class = self
self = {}

self.size = size
self.map = fill_with_zeroes(size)

return setmetatable(self, { __index = class })
end

function HeightMap:get_value(z, x)
local h = self.size
local w = self.size

if x < 0 or z < 0 or x > w-1 or z > h-1 then
return nil
end

return self.map[z+1][x+1]
end

function HeightMap:set_value(z, x, val)
local h = self.size
local w = self.size

if x < 0 or z < 0 or x > w-1 or z > h-1 then
return
end

self.map[z+1][x+1] = val
end


return HeightMap
20 changes: 0 additions & 20 deletions mods/lord/World/mountgen/src/generator/height_map.lua

This file was deleted.

1 change: 0 additions & 1 deletion mods/lord/World/mountgen/src/mountgen.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ mountgen = {}
require('algorithms.cone')
require('algorithms.diamond_square')
require('generator')
require('generator.height_map')
require('map')
require('ui')

Expand Down

0 comments on commit dde16a6

Please sign in to comment.