diff options
Diffstat (limited to 'server/noise.lua')
-rw-r--r-- | server/noise.lua | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/server/noise.lua b/server/noise.lua new file mode 100644 index 0000000..1480448 --- /dev/null +++ b/server/noise.lua @@ -0,0 +1,96 @@ +local Pos = require"common.coords".Pos +local tau = 2*math.pi + +math.randomseed(os.time()) + +local function random_unit_vec() + local theta = math.random()*tau + return Pos.make(math.cos(theta),math.sin(theta)) +end +local function lerp(a,b,t) return (1-t)*a + t*b end +local function smoothstep(x) + if x<0 then return 0 end + if x>1 then return 1 end + return x*x*(3 - 2*x) +end +local function slerp(a,b,t) return lerp(a,b,smoothstep(t)) end + +local NoiseGen = {} +NoiseGen.__index = NoiseGen +function NoiseGen.make() + local grid = {} + setmetatable(grid,{__index=function(t,k) t[k] = {} return t[k] end}) + return setmetatable({grid=grid},NoiseGen) +end +function NoiseGen.vertex(self,ix,iy) + local v = self.grid[ix][iy] + if v then return v end + vv = random_unit_vec() + self.grid[ix][iy] = vv + return vv +end + +function NoiseGen.at(self,x,y) + local x0 = math.floor(x) + local y0 = math.floor(y) + local x1 = x0 + 1 + local y1 = y0 + 1 + + local v00 = self:vertex(x0,y0) + local v01 = self:vertex(x0,y1) + local v10 = self:vertex(x1,y0) + local v11 = self:vertex(x1,y1) + + local p = Pos.make + local d00 = v00:dot(p(x-x0,y-y0)) + local d01 = v01:dot(p(x-x0,y-y1)) + local d10 = v10:dot(p(x-x1,y-y0)) + local d11 = v11:dot(p(x-x1,y-y1)) + + local q0 = slerp(d00,d01,y-y0) + local q1 = slerp(d10,d11,y-y0) + local z = slerp(q0,q1,x-x0) + return z +end + +local NoiseAgg = {} +NoiseAgg.__index = NoiseAgg +function NoiseAgg.make(things) + return setmetatable({things=things or {}},NoiseAgg) +end +function NoiseAgg.make_perlin_octaves(nocts) + local things = {} + for i=1,nocts do + table.insert(things,{amp=2^i,scale=2^(nocts-i),gen=NoiseGen.make()}) + end + return NoiseAgg.make(things) +end +function NoiseAgg.at(self,x,y) + local n = 0 + local t = 0 + assert(#self.things>0,"can't generate noise with no noise things") + for _,thing in ipairs(self.things) do + local gen,scale,amp = thing.gen,thing.scale,thing.amp + n = n + amp + t = t + gen:at(x*scale,y*scale)*amp + end + return t/n +end + +-- local chars = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. " + +-- local scale = 3 + +-- for x=1,10-10/40,10/40 do +-- for y = 1,10-10/60,10/60 do + +-- local n = at(1+(x-1)/scale,1+(y-1)/scale) +-- local nn = (n +1)/2 +-- local nnn = 1+nn*#chars +-- local c = chars:sub(nnn,nnn) +-- io.write(c) +-- end +-- io.write("\n") +-- end + +return {NoiseGen=NoiseGen,NoiseAgg=NoiseAgg} |