266 lines
8.9 KiB
Plaintext
266 lines
8.9 KiB
Plaintext
local slate_color = Color3.fromRGB(124, 124, 124)
|
|
local grass_color = Color3.fromRGB(58, 125, 21) -- Color3.fromRGB(58, 125, 21)
|
|
|
|
local part = Instance.new("Part")
|
|
part.Anchored = true
|
|
part.CanCollide = true
|
|
part.Parent = game.Workspace
|
|
part.Material = Enum.Material.Slate
|
|
part.Shape = Enum.PartType.Block
|
|
part.Color = slate_color
|
|
local boom = 10
|
|
local math_abs = math.abs
|
|
local math_max = math.max
|
|
local math_min = math.min
|
|
local math_noise = math.noise
|
|
local table_create = table.create
|
|
local chunks = {}
|
|
local function _n(x,y,z) -- Legacy noise
|
|
local h = (math_noise(x*0.00015,y*0.00015,z*0.00015)*2)^3
|
|
local m = math_noise(x*0.00005,y*0.00005,z*0.00005)
|
|
local s = math_noise(x*0.03,y*0.03,z*0.03)
|
|
local n = math_noise(x*0.0015,y*0.0015*h,z*0.0015)
|
|
y = y - 512 + h * 512
|
|
return ((n)*h-y*0.0005)*boom
|
|
--[[local h = math_noise(x*0.0005,0.123,z*0.0005)*4
|
|
return (math_noise(x*0.0015,y*0.0015*h,z*0.0015)*2*h+math_noise(x*0.005,y*0.005*h,z*0.005)*h-(y+h*10)*0.005)*boom]]
|
|
end
|
|
local function n_cloud(x,y,z)
|
|
return math_noise(x*0.0002,y*0.0002,z*0.0002)
|
|
end
|
|
local function n_imaginarium(x,y,z) -- Current noise terrain profile
|
|
x = x * 2
|
|
y = y * 2 + 1024
|
|
z = z * 2
|
|
local conduit = (1-math_abs(math_noise(x*0.00005,y*0.00005,z*0.00005)))^4 + 0.05
|
|
local hillsong = math_noise(x*0.0015,y*0.0015,z*0.0015)*2
|
|
local titans = math_noise(x*0.0002,y*0.0002,z*0.0002)*16
|
|
return ((titans + hillsong) * conduit - y * 0.00075) * boom
|
|
end
|
|
local function n_tranquility(x,y,z) -- Fields and hills
|
|
y = y - 512
|
|
local tranquility = math_noise(x*0.0001,y*0.0001,z*0.0001)
|
|
local turbulence = math_noise(x*0.0008,y*0.0008,z*0.0008)
|
|
local atmosphere = math_noise(x*0.0005,y*0.0005,z*0.0005)
|
|
return ((atmosphere + turbulence) * tranquility - y * 0.0001) * boom
|
|
end
|
|
local function n_satisfaction(x,y,z) --
|
|
return 0
|
|
end
|
|
--[[local function fol(x,y,z)
|
|
local density = math_noise(x*0.0001,y*0.0001,z*0.0001)
|
|
local b = math_noise(x*0.001,y*0.001,z*0.001) > 0.5
|
|
--local t = math_noise(x*0.001,y*0.001,z*0.001) > 0.3
|
|
return b
|
|
end]]
|
|
local function p(x,y,z,f,parent) -- Create a part at a size
|
|
local p = part:Clone()
|
|
p.Parent = parent
|
|
p.Size = Vector3.one*f
|
|
p.Position = Vector3.new(x,y,z)
|
|
return p
|
|
end
|
|
local compensate = 4 -- Make terrain puffy so the octree system can see it clearly
|
|
local function m(f)
|
|
return boom*compensate
|
|
end
|
|
-- Preinitialise a data structure to hold game.Workspace.Terrain form of terrain data
|
|
local base = 4
|
|
local mat
|
|
local occ
|
|
do
|
|
local _otx = table_create(8)
|
|
for _x=1,8 do
|
|
local _oty = table_create(8)
|
|
for _y=1,8 do
|
|
_oty[_y] = table_create(8)
|
|
end
|
|
_otx[_x] = _oty
|
|
end
|
|
local _mtx = table_create(8)
|
|
for _x=1,8 do
|
|
local _mty = table_create(8)
|
|
for _y=1,8 do
|
|
_mty[_y] = table_create(8)
|
|
end
|
|
_mtx[_x] = _mty
|
|
end
|
|
occ = _otx
|
|
mat = _mtx
|
|
end
|
|
-- Use the preinitialised data structure from above to render in a chunk of roblox style terrain
|
|
local function ter(x,y,z,f)
|
|
for ix=1,8 do
|
|
for iy=1,8 do
|
|
for iz=1,8 do
|
|
occ[ix][iy][iz] = n(x+(ix-4)*4,y+(iy-4)*4,z+(iz-4)*4)
|
|
mat[ix][iy][iz] = Enum.Material.Grass
|
|
end
|
|
end
|
|
end
|
|
workspace.Terrain:WriteVoxels(Region3.new(Vector3.new(x,y,z)-Vector3.one*f*0.5,Vector3.new(x,y,z)+Vector3.one*f*0.5),4,mat,occ)
|
|
end
|
|
local voro = require(script.Parent.CellularModule) -- Voronoi noise library
|
|
local man = voro.man
|
|
local mag = voro.mag
|
|
local che = voro.che
|
|
local cheman = voro.cheman
|
|
local vor = voro.vor
|
|
local squir = voro.squircle
|
|
local function fol(x,y,z)
|
|
x = x - x % 32
|
|
y = y - y % 32
|
|
z = z - z % 32
|
|
return math_noise(x*0.00025,y*0.00025-2,z*0.00025)
|
|
end
|
|
local function act(x)
|
|
if x > -5 then return 0.8 end
|
|
--if x > -0.1 then return 0.4 end
|
|
return 0
|
|
end
|
|
--local pieces = require(script.Parent.TownPieceModule)
|
|
--local block = pieces.block
|
|
road = function(x,y,z)
|
|
local n1,c1 = vor(x*0.01,y*0.01,z*0.01,che)
|
|
local n2,c2 = vor(x*0.002,y*0.002,z*0.002,che) -- 1 = crowded, 0 = empty
|
|
local c1x = c1.X*100
|
|
local c1y = c1.Y*100
|
|
local c1z = c1.Z*100
|
|
local d = n(c1x,c1y,c1z)*0.025 -- 0 = surface, -1 = air
|
|
if n1 > -d and d > -0.3 --[[and n2 < 0.5]] then
|
|
-- Is centre near ground, is building (thinning towards top), is not road, is centre within bounds
|
|
return c1x,c1y,c1z
|
|
end
|
|
--return vor(x*0.002,y*0.002,z*0.002,cheman) + d + 0.3
|
|
end
|
|
|
|
local surf = require(script.Parent.SurfaceNetModule) -- Surface terrain library
|
|
local vox = surf.voxel
|
|
local rand = Random.new()
|
|
local na = Vector3.new(-1,-1,-1) -- Vectors for cardinal directions (corners of a cube)
|
|
local nb = Vector3.new(-1,1,1)
|
|
local nc = Vector3.new(1,-1,1)
|
|
local nd = Vector3.new(1,1,-1)
|
|
local ne = Vector3.new(-1,-1,1)
|
|
local nf = Vector3.new(-1,1,-1)
|
|
local ng = Vector3.new(1,-1,-1)
|
|
local nh = Vector3.new(-1,-1,-1)
|
|
local trees = game.ReplicatedStorage.Foliage:GetChildren()
|
|
local no_trees = #trees
|
|
local rand = Random.new()
|
|
local struct = require(script.Parent.StructureModule)
|
|
@native
|
|
local function chunk(x,y,z,f,b,stuff,v,n)
|
|
struct.make_chunk(x,y,z,f,n)
|
|
local vf = 1/4096
|
|
local parent = stuff.parent
|
|
local n1,c2 = vor(x*vf,y*vf,z*vf,man)
|
|
local val = n(x,y,z)
|
|
local grass = stuff.grass.make_quad -- Quad making function from the surface factory for each material
|
|
local slate = stuff.slate.make_quad
|
|
local bd
|
|
local function s(x,y,z,f)
|
|
if not b then b = 32 end
|
|
local fr = f * 0.25
|
|
-- Shift of positions (XYZ axes)
|
|
local lx = x+fr
|
|
local ly = y+fr
|
|
local lz = z+fr
|
|
local hx = x-fr
|
|
local hy = y-fr
|
|
local hz = z-fr
|
|
-- Noise values (corners)
|
|
local _a,_b,_c,_d,_e,_f,_g,_h = n(lx,ly,lz),n(hx,ly,lz),n(lx,hy,lz),n(lx,ly,hz),n(hx,hy,lz),n(hx,ly,hz),n(lx,hy,hz),n(hx,hy,hz)
|
|
local o,dx,dy,dz = n(x,y,z),n(x+1,y,z),n(x,y+1,z),n(x,y,z+1) -- Gradient of surface noises
|
|
local norm = Vector3.new(o-dx,o-dy,o-dz).Unit---((_a)*(na)+(_b)*(nb)+(_c)*(nc)+(_d)*(nd)+(_e)*(ne)+(_f)*(nf)+(_g)*(ng)+(_h)*(nh)).Unit --GRAD
|
|
local sum = (_a+_b+_c+_d+_e+_f+_g+_h)*0.125 -- Average noise from sample
|
|
--[[if f == b and fol(x,y,z) > 0.62 and sum < 0 then
|
|
local fs = fr * 2 - 16
|
|
for bx = x-fs,x+fs,32 do
|
|
for by = y-fs,y+fs,32 do
|
|
for bz = z-fs,z+fs,32 do
|
|
local cx,cy,cz = road(bx,by,bz)
|
|
if cx then pieces.block(bx,by,bz,32,road,cx,cy,cz) end
|
|
end
|
|
end
|
|
end
|
|
--vox(x,y,z,b,brick,road)
|
|
end]]
|
|
if math_max(_a,_b,_c,_d,_e,_f,_g,_h) < -m(f) then -- Nothing to do
|
|
return
|
|
elseif math_min(_a,_b,_c,_d,_e,_f,_g,_h) > m(f) then --
|
|
--[[if b == 4 and f == 32 then
|
|
workspace.Terrain:FillRegion(Region3.new(Vector3.new(x,y,z)-Vector3.one*f*0.5,Vector3.new(x,y,z)+Vector3.one*f*0.5),4,Enum.Material.Grass)
|
|
else]]
|
|
--if b ~= 4 then p(x,y,z,f) end
|
|
--end
|
|
else -- We are near the surface
|
|
--[[if math_abs(norm.Y) < 0.4 and math_abs(sum) < 0.1 and f <= b then
|
|
local part = p(x,y,z,f)
|
|
part.CFrame = CFrame.lookAlong(part.Position,norm)
|
|
part.Size = Vector3.new(part.Size.X*(rand:NextNumber()+2),part.Size.Y*(rand:NextNumber()+2),part.Size.Z*(rand:NextNumber()+1))*2
|
|
part.Position = part.Position + norm * f * 0.5
|
|
return
|
|
end]]
|
|
if f == v then
|
|
if norm.Y < 0.5 then
|
|
vox(x,y,z,v,slate,n,parent)
|
|
else
|
|
vox(x,y,z,v,grass,n,parent)
|
|
end
|
|
end
|
|
if f == b then -- We are at the rendering level for this chunk
|
|
-- Broad building check
|
|
if math_abs(sum) < 0.5 and f >= 256 then -- If
|
|
if norm.Y < 0.7 then -- Rock
|
|
local part = p(x,y,z,math.clamp(f*2.5,0,512),parent)
|
|
part.CFrame = CFrame.lookAlong(part.Position-norm*f,norm)
|
|
part.Size = Vector3.one * f * 2
|
|
else -- Foliage (why does this never run?)
|
|
if f > 256 then
|
|
local part = p(x,y,z,f*2.5,parent)
|
|
part.Material = Enum.Material.Grass
|
|
part.Color = grass_color
|
|
part.Shape = Enum.PartType.Ball
|
|
end
|
|
end
|
|
elseif f == 512 and rand:NextInteger(1,5) == 5 and n_cloud(x,y,z) > 0 then
|
|
local part = p(x,y,z,2048*(rand:NextNumber()+1),parent)
|
|
part.Material = Enum.Material.SmoothPlastic
|
|
part.Transparency = 0.7
|
|
part.Shape = Enum.PartType.Ball
|
|
part.Size = part.Size * rand:NextInteger(1,4) * 0.5
|
|
end
|
|
else -- We are too large, recurse into lower octrees
|
|
f = f * 0.5
|
|
s(lx,ly,lz,f) s(hx,ly,lz,f) s(lx,hy,lz,f) s(lx,ly,hz,f) s(hx,hy,lz,f) s(hx,ly,hz,f) s(lx,hy,hz,f) s(hx,hy,hz,f)
|
|
end
|
|
end
|
|
end
|
|
s(x,y,z,f)
|
|
end
|
|
|
|
local grass = surf.make_wedges(nil,{Material = Enum.Material.Grass, Color = grass_color}) -- Terrain constructors??? WedgePart?
|
|
local slate = surf.make_wedges(nil,{Material = Enum.Material.Slate, Color = slate_color})
|
|
local function write_chunk(x,y,z,r)
|
|
local town_folder = Instance.new("Folder")
|
|
town_folder.Parent = game.Workspace.Terrain
|
|
local folder = Instance.new("Folder")
|
|
folder.Parent = game.Workspace.Terrain
|
|
local root = Vector3.new(x,y,z)*512
|
|
|
|
local b = 512
|
|
r = math.floor(r)
|
|
if r == 1 then b = 512
|
|
elseif r == 2 then b = 256
|
|
elseif r >= 3 then b = 128
|
|
--elseif r >= 4 then b = 64
|
|
end
|
|
--task.desynchronize() -- enter parallel and generate the chunk
|
|
chunk(x*1024,y*1024,z*1024,1024,b,{grass = grass, slate = slate, parent = folder, town_parent = town_folder},b,n_imaginarium)
|
|
--task.synchronize() -- come back to us
|
|
|
|
return folder,town_folder
|
|
end
|
|
|
|
return {write_chunk = write_chunk} |