Files
PlaneBuilding/scratch/dct2/SurfaceNetModule
T

236 lines
6.9 KiB
Plaintext

local cellular = require(script.Parent.CellularModule)
local module = {}
local store = game.ReplicatedStorage:WaitForChild("Structure")
local function put(model,x,y,z)
model = model:Clone()
model:PivotTo(CFrame.new(Vector3.new(x,y,z)))
model.Parent = game.Workspace.Terrain
end
local function block(x,y,z,sx,sy,sz)
local part = Instance.new("Part")
part.Material = Enum.Material.Slate
part.Parent = game.Workspace.Terrain
part.Size = Vector3.new(sx,sy,sz)
part.Position = Vector3.new(x,y,z)
part.Transparency = 0
part.Anchored = true
part.CanCollide = false
return part
end
--[[
-- Create a list based tree for octree access
local function create_octree_heap(s,l)
local sum = 0
local s_ = l
local amount = 1
repeat
s_ = s_ * 2
sum = sum + amount
amount = amount * 8
until s_ ~= s
print(sum)
local tab = table.create()
end
local function index_octree_heap(x,y,z)
end
]] -- probably not actually fast enough than direct hash access?. optimise later...
-- Create a list based tree for 6 bit access
local function create_6way_heap()
local tab = table.create(64)
for index,_ in ipairs(tab) do
tab[index] = {}
end
return tab
end
-- Index a 6way heap by wall values
local function index_6way_heap(heap,px,py,pz,nx,ny,nz)
return heap[1 + px * 1 + py * 2 + pz * 4 + nx * 8 + ny * 16 + nz * 32]
end
local function setindex_6way_heap(heap,px,py,pz,nx,ny,nz,v)
heap[1 + px * 1 + py * 2 + pz * 4 + nx * 8 + ny * 16 + nz * 32] = v
end
local l = -10
-- Index a 6way heap by wall values from a noise function
local function access_6way_heap(heap,x,y,z,f,n)
f = f * 0.5
local px = 0 if n(x+f,y,z)>l then px = 1 end
local py = 0 if n(x,y+f,z)>l then py = 1 end
local pz = 0 if n(x,y,z+f)>l then pz = 1 end
local nx = 0 if n(x-f,y,z)>l then nx = 1 end
local ny = 0 if n(x,y-f,z)>l then ny = 1 end
local nz = 0 if n(x,y,z-f)>l then nz = 1 end
return index_6way_heap(heap,px,py,pz,nx,ny,nz)
end
local function preload_6way_heap(heap,stuff)
for _,piece in pairs(stuff:GetChildren()) do
local n = piece.Name
local x = 0 if n:match("PZ") then x = 1 end
local y = 0 if n:match("PY") then y = 1 end
local z = 0 if n:match("PX") then z = 1 end
local nx = 0 if n:match("NZ") then nx = 1 end
local ny = 0 if n:match("NY") then ny = 1 end
local nz = 0 if n:match("NX") then nz = 1 end
piece.PrimaryPart = piece:FindFirstChild("Root") or piece:FindFirstChildWhichIsA("BasePart")
piece.PrimaryPart:PivotTo(piece.PrimaryPart.CFrame * CFrame.Angles(0,math.pi * 0.5,0))
if not piece.PrimaryPart then print(piece) error() end
local p0 = piece:Clone() p0.Name = p0.Name.."_0"
--p0.PrimaryPart:PivotTo(p0.PrimaryPart.CFrame * CFrame.Angles(0,-math.pi*0.0,0))
setindex_6way_heap(heap,x,y,z,nx,ny,nz,p0)
local p90 = piece:Clone() p90.Name = p90.Name.."_90"
p90.PrimaryPart:PivotTo(p90.PrimaryPart.CFrame * CFrame.Angles(0,math.pi*0.5,0))
setindex_6way_heap(heap,nz,y,x,z,ny,nx,p90)
local p180 = piece:Clone() p180.Name = p180.Name.."_180"
p180.PrimaryPart:PivotTo(p180.PrimaryPart.CFrame * CFrame.Angles(0,math.pi*1.0,0))
setindex_6way_heap(heap,nx,y,nz,x,ny,z,p180)
local p270 = piece:Clone() p270.Name = p270.Name.."_270"
p270.PrimaryPart:PivotTo(p270.PrimaryPart.CFrame * CFrame.Angles(0,math.pi*1.5,0))
setindex_6way_heap(heap,z,y,nx,nz,ny,x,p270)
-- Anchor the whole thing into one assembly
for _,piece in pairs({p0,p90,p180,p270}) do
for _,part in pairs(piece:GetChildren()) do
if part:IsA("BasePart") and part ~= piece.PrimaryPart then
local weld = Instance.new("WeldConstraint")
weld.Parent = piece
weld.Name = "BuildingWeld"
weld.Part0 = part
weld.Part1 = piece.PrimaryPart
end
end
piece.PrimaryPart.Anchored = true
end
end
end
local heap_6way_32_bank = create_6way_heap()
preload_6way_heap(heap_6way_32_bank,store.Bank)
local heap_6way_64_slums = create_6way_heap()
preload_6way_heap(heap_6way_64_slums,store.Slums)
-- Rule: Any block only needs to support up to half away from any connected wall.
-- Any block is allowed to protrude up to half into empty space from no wall.
local function building_32(x,y,z,sx,sy,sz)
local b = block(x,y,z,sx,sy,sz)
b.Color = Color3.new(0.568627, 0.341176, 0.152941)
b.Material = Enum.Material.WoodPlanks
end
local function support_32(x,y,z,sx,sy,sz)
local b = block(x,y,z,sx,sy,sz)
b.Color = Color3.new(0.6, 0.6, 0.6)
b.Material = Enum.Material.Slate
end
local function cover_128_32(x,y,z,n)
local s = 128 * 0.5
local f = 32
local f2 = f * 0.5
for ox = -s + f2 + x,s - f2 + x,f do
for oy = -s + f2 + y,s - f2 + y,f do
for oz = -s + f2 + z,s - f2 + z,f do
local v = n(ox,oy,oz)
if v > l then
local jigsaw = access_6way_heap(heap_6way_32_bank,ox,oy,oz,32,n)
if jigsaw then
local blk = jigsaw:Clone()
blk.Parent = game.Workspace
blk:PivotTo(CFrame.new(ox,oy,oz))
end
end
end
end
end
end
local function compose_128_32(x,y,z,n)
local rx = x - 64 + 16
local ry = y - 64 + 16
local rz = z - 64 + 16
local i = 128
local px = n(x+i,y,z)>l
local py = n(x,y+i,z)>l
local pz = n(x,y,z+i)>l
local nx = n(x-i,y,z)>l
local ny = n(x,y-i,z)>l
local nz = n(x,y,z-i)>l
local function p(x,y,z,...) -- px,py...
local jigsaw = index_6way_heap(heap_6way_32_bank,...)
if jigsaw then
local blk = jigsaw:Clone()
blk.Parent = game.Workspace
blk:PivotTo(CFrame.new(x,y,z))
end
end
local s = 128 * 0.5
local f = 32
local f2 = f * 0.5
for dx = -3,3,2 do
for dy = -3,3,2 do
for dz = -3,3,2 do
local _px = 1 if not px and dx == 1 then _px = 0 end
local _py = 1 if not py and dy == 1 then _py = 0 end
local _pz = 1 if not pz and dz == 1 then _pz = 0 end
local _nx = 1 if not nx and dx == -1 then _nx = 0 end
local _ny = 1 if not ny and dy == -1 then _ny = 0 end
local _nz = 1 if not nz and dz == -1 then _nz = 0 end
if
(not px and dx == 3) or
(not py and dy == 3) or
(not pz and dz == 3) or
(not nx and dx == -3) or
(not ny and dy == -3) or
(not nz and dz == -3)
then continue end
local jigsaw = index_6way_heap(heap_6way_32_bank,_px,_py,_pz,_nx,_ny,_nz)
if jigsaw then
local blk = jigsaw:Clone()
blk.Parent = game.Workspace
blk:PivotTo(CFrame.new(dx * f2 + x,dy * f2 + y,dz * f2 + z))
end
end
end
end
end
local function cover_1024_128(x,y,z,n)
local s = 1024 * 0.5
local f = 64
local f2 = f * 0.5
for ox = -s + f2 + x,s - f2 + x,f do
for oy = -s + f2 + y,s - f2 + y,f do
for oz = -s + f2 + z,s - f2 + z,f do
local v = n(ox,oy,oz)
--local blk = block(ox,oy,oz,128,128,128)
if v > 0 then
--put(store.Support1,ox,oy,oz)
elseif v > l then
local jigsaw = access_6way_heap(heap_6way_64_slums,ox,oy,oz,64,n)
if jigsaw then
local blk = jigsaw:Clone()
blk.Parent = game.Workspace
blk:PivotTo(CFrame.new(ox,oy,oz))
end
--compose_128_32(ox,oy,oz,n)
end
end
end
end
end
function module.make_chunk(x,y,z,f,n)
cover_1024_128(x,y,z,n)
end
return module