summaryrefslogtreecommitdiff
path: root/server/noise.lua
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2023-02-03 01:32:09 +0000
committerubq323 <ubq323@ubq323.website>2023-02-03 01:32:09 +0000
commitec6a391cb9cf0c0feac0fe3615a59cc7cb6db2d5 (patch)
tree1893ad4fe5dc651370411f2bc84060cd7c0465cb /server/noise.lua
parent04664ee48de5fc8b06a584e20a4b75c41dafa558 (diff)
drawing changes, world generation, perlin noise
Diffstat (limited to 'server/noise.lua')
-rw-r--r--server/noise.lua96
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}