random-stuff/heavbiome/perlin.lua

134 lines
2.7 KiB
Lua

local defaultSeed = 1337
local dot_product = {
[0x0]=function(x,y,z) return x + y end,
[0x1]=function(x,y,z) return -x + y end,
[0x2]=function(x,y,z) return x - y end,
[0x3]=function(x,y,z) return -x - y end,
[0x4]=function(x,y,z) return x + z end,
[0x5]=function(x,y,z) return -x + z end,
[0x6]=function(x,y,z) return x - z end,
[0x7]=function(x,y,z) return -x - z end,
[0x8]=function(x,y,z) return y + z end,
[0x9]=function(x,y,z) return -y + z end,
[0xA]=function(x,y,z) return y - z end,
[0xB]=function(x,y,z) return -y - z end,
[0xC]=function(x,y,z) return y + x end,
[0xD]=function(x,y,z) return -y + z end,
[0xE]=function(x,y,z) return y - x end,
[0xF]=function(x,y,z) return -y - z end
}
local grad = function(hash, x,y,z)
return dot_product[hash % 0x10](x,y,z)
end
local fade = function(t)
return t * t * t * (t * (t * 6 - 15) + 10)
end
local lerp = function(t,a,b)
return a + t * (b - a)
end
local generatePermutation = function(seed)
math.randomseed(seed)
local permutation = {0}
for i=1,255 do
table.insert(permutation,math.random(1,#permutation+1),i)
end
local p = {}
for i=0,255 do
p[i] = permutation[i+1]
p[i+256] = permutation[i+1]
end
return p
end
perlin = {}
perlin.__index = perlin
perlin.noise = function(self,x,y,z)
y = y or 0
z = z or 0
local xi = math.floor(x) % 0x100
local yi = math.floor(y) % 0x100
local zi = math.floor(z) % 0x100
x = x - math.floor(x)
y = y - math.floor(y)
z = z - math.floor(z)
local u = fade(x)
local v = fade(y)
local w = fade(z)
local A, AA, AB, AAA, ABA, AAB, ABB, B, BA, BB, BAA, BBA, BAB, BBB
A = self.p[xi ] + yi
AA = self.p[A ] + zi
AB = self.p[A+1 ] + zi
AAA = self.p[ AA ]
ABA = self.p[ AB ]
AAB = self.p[ AA+1 ]
ABB = self.p[ AB+1 ]
B = self.p[xi+1] + yi
BA = self.p[B ] + zi
BB = self.p[B+1 ] + zi
BAA = self.p[ BA ]
BBA = self.p[ BB ]
BAB = self.p[ BA+1 ]
BBB = self.p[ BB+1 ]
return lerp(w,
lerp(v,
lerp(u,
grad(AAA,x,y,z),
grad(BAA,x-1,y,z)
),
lerp(u,
grad(ABA,x,y-1,z),
grad(BBA,x-1,y-1,z)
)
),
lerp(v,
lerp(u,
grad(AAB,x,y,z-1), grad(BAB,x-1,y,z-1)
),
lerp(u,
grad(ABB,x,y-1,z-1), grad(BBB,x-1,y-1,z-1)
)
)
)
end
setmetatable(perlin,{
__call = function(self,seed)
seed = seed or defaultSeed
return setmetatable({
seed = seed,
p = generatePermutation(seed),
},self)
end
})
--[[
EXAMPLE
local p1 = perlin(1338)
local p2 = perlin(1337)
local x,y,z = 1.0,2.0,3.0
print(p1:noise(x,y,z))
print(p2:noise(x,y,z))
>> 0.23456
>> 0.47598
--]]