Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Terrain height map generation — Gideros Forum

Terrain height map generation

JohnJohn Member
edited February 26 in Code snippets
Created by AI so may not be most efficient method of doing this
HeightMap = Core.class()
 
function HeightMap:init(w, h, seed)
    self.w = w or 256
    self.h = h or 256
    math.randomseed(seed or os.time())
 
    self.perm = {}
    for i = 0, 511 do
        self.perm[i] = math.random(0, 255)
    end
 
    self.grads = {
        {1,1}, {-1,1}, {1,-1}, {-1,-1},
        {1,0}, {-1,0}, {0,1}, {0,-1},
        {2,1}, {-2,1}, {1,2}, {-1,2}
    }
end
 
function HeightMap:generate(scale, oct, pers)
    local rt = RenderTarget.new(self.w, self.h)
    local pix = Pixel.new(0, 1)
 
    local min = math.huge
    local max = -math.huge
    local values = {}
 
    -- Raw noise generation
    for y = 0, self.h-1 do
        for x = 0, self.w-1 do
            local total = 0
            local amp = 1
            local freq = scale or 0.01
 
            for _ = 1, oct or 6 do
                local nx = x * freq
                local ny = y * freq
 
                -- Grid coordinates
                local x0 = math.floor(nx)
                local y0 = math.floor(ny)
                local x1 = x0 + 1
                local y1 = y0 + 1
 
                -- Interpolation weights
                local sx = nx - x0
                local sy = ny - y0
 
                -- Gradient indices
                local gi00 = (self.perm[x0 % 255 + self.perm[y0 % 255]] % 12) + 1
                local gi10 = (self.perm[x1 % 255 + self.perm[y0 % 255]] % 12) + 1
                local gi01 = (self.perm[x0 % 255 + self.perm[y1 % 255]] % 12) + 1
                local gi11 = (self.perm[x1 % 255 + self.perm[y1 % 255]] % 12) + 1
 
                -- Dot products
                local n00 = self.grads[gi00][1] * sx + self.grads[gi00][2] * sy
                local n10 = self.grads[gi10][1] * (sx-1) + self.grads[gi10][2] * sy
                local n01 = self.grads[gi01][1] * sx + self.grads[gi01][2] * (sy-1)
                local n11 = self.grads[gi11][1] * (sx-1) + self.grads[gi11][2] * (sy-1)
 
                -- Smooth interpolation
                local u = sx * sx * (3 - 2 * sx)
                local v = sy * sy * (3 - 2 * sy)
 
                local i0 = n00 + u * (n10 - n00)
                local i1 = n01 + u * (n11 - n01)
                total = total + (i0 + v * (i1 - i0)) * amp
 
                amp = amp * (pers or 0.5)
                freq = freq * 2
            end
 
            values[y*self.w + x] = total
            min = math.min(min, total)
            max = math.max(max, total)
        end
    end
 
    -- Normalize and render
    local range = math.max(0.001, max - min)
    for y = 0, self.h-1 do
        for x = 0, self.w-1 do
            local val = (values[y*self.w + x] - min) / range
            val = val ^ 1.5  -- Contrast boost
            local c = math.floor(255 * val)
            pix:setColor(c << 16 | c << 8 | c, 1)
            rt:draw(pix, x, y)
        end
    end
 
    return Bitmap.new(rt)
end
 
 
local heightmap = HeightMap.new(512, 512)
 
local terrain = heightmap:generate(0.002, 8, 0.7) -- mountains
--terrain = heightmap:generate(0.02, 4, 0.4) -- hills
--terrain = heightmap:generate(0.01, 6, 0.6) -- ocean
--terrain = heightmap:generate(0.005, 10, 0.8) -- alien
 
terrain:setPosition(0, 0)
stage:addChild(terrain)
Key Parameters:

scale (0.001-0.1): Zoom level (lower = bigger features)

octaves (1-10): Detail layers (more = rougher terrain)

persistence (0.3-0.9): Roughness control (higher = more jagged)

Likes: MoKaLux

+1 -1 (+1 / -0 )Share on Facebook

Comments

Sign In or Register to comment.