mirror of
https://github.com/DramaticShape/DramaticShapeVoxelMod.git
synced 2026-08-12 15:50:52 +02:00
update oak's pc
This commit is contained in:
+37
-12
@@ -3270,16 +3270,21 @@ return {
|
||||
roofRows = 19, roofBack = 16, roofFront = 0, roofCycle = { 2, 13 },
|
||||
slab = 3, frontEave = 0, ledge = nil, depth = 2,
|
||||
},
|
||||
-- F02: the computer bank on the lab's west table (OAKS_LAB cell
|
||||
-- 0,1) -- the one FACADE-ONLY template: rows 0-14 are machines
|
||||
-- drawn face-on (monitor and keys, the centre console, the right
|
||||
-- cabinet) over the lab-table fascia and base bands, and nothing
|
||||
-- is drawn from above. roofRows = 0, so the whole drawing
|
||||
-- extrudes -- the house facade treatment with no roof band; the
|
||||
-- roof fields are inert and the recess pass sinks every framed
|
||||
-- pane (screens, keys, the cabinet's inset face) into relief on
|
||||
-- its own. Same drawing, same grid, stands in the Hall of Fame
|
||||
-- on the GYM atlas -- registered there below.
|
||||
-- F02: the computer desk on the lab's west side (OAKS_LAB cell
|
||||
-- 0,1) -- the one DESK-SET template: the pipeline's region
|
||||
-- classification at PART granularity (see Buildings
|
||||
-- deskSetModel). The desk is the sibling lab table (fascia rows
|
||||
-- 16-18, base 19-21); on it stand a monitor over its keyboard
|
||||
-- (left), a computer tower over a keyboard and mouse (middle),
|
||||
-- and a sheet of paper LYING FLAT (right). Upright parts anchor
|
||||
-- their drawn bottom row to the desk's top plane and wear their
|
||||
-- own drawn tops as lids; flat parts lie one voxel proud at
|
||||
-- drawn row = depth row -- the same 1:1 the tabletop itself is
|
||||
-- drawn with. The roof fields are inert (roofRows = 0 keeps the
|
||||
-- recess scan over the whole drawing, which is what sinks the
|
||||
-- monitor's screen and the tower's slots). Same drawing, same
|
||||
-- grid, stands in the Hall of Fame on the GYM atlas --
|
||||
-- registered there below.
|
||||
{
|
||||
id = "lab_computers",
|
||||
tiles = {
|
||||
@@ -3289,6 +3294,16 @@ return {
|
||||
},
|
||||
roofRows = 0, roofBack = 0, roofFront = 0, roofCycle = { 0, 0 },
|
||||
slab = 0, frontEave = 0, ledge = nil, depth = 2,
|
||||
desk = { fascia = { 16, 18 }, base = { 19, 21 } },
|
||||
parts = {
|
||||
{ kind = "upright", x = { 2, 13 }, top = { 0, 2 },
|
||||
facade = { 3, 10 }, depth = 4 }, -- the monitor
|
||||
{ kind = "flat", x = { 1, 13 }, rows = { 11, 14 } }, -- keyboard
|
||||
{ kind = "upright", x = { 14, 21 }, top = { 0, 3 },
|
||||
facade = { 4, 10 }, depth = 6 }, -- the tower
|
||||
{ kind = "flat", x = { 14, 21 }, rows = { 11, 14 } }, -- keys+mouse
|
||||
{ kind = "flat", x = { 22, 30 }, rows = { 1, 14 } }, -- the paper
|
||||
},
|
||||
},
|
||||
-- F03: the empty north table beside it (OAKS_LAB cell 2,1): the
|
||||
-- starter table's band table verbatim on a grid two tiles
|
||||
@@ -3307,8 +3322,8 @@ return {
|
||||
|
||||
GYM = {
|
||||
-- F02 again: the Hall of Fame's recording machine is the lab's
|
||||
-- computer bank drawing, tile for tile, on the GYM atlas (one
|
||||
-- placement: HALL_OF_FAME cell 4,1). Same band table as the DOJO
|
||||
-- computer desk drawing, tile for tile, on the GYM atlas (one
|
||||
-- placement: HALL_OF_FAME cell 4,1). Same part table as the DOJO
|
||||
-- entry above.
|
||||
{
|
||||
id = "lab_computers",
|
||||
@@ -3319,6 +3334,16 @@ return {
|
||||
},
|
||||
roofRows = 0, roofBack = 0, roofFront = 0, roofCycle = { 0, 0 },
|
||||
slab = 0, frontEave = 0, ledge = nil, depth = 2,
|
||||
desk = { fascia = { 16, 18 }, base = { 19, 21 } },
|
||||
parts = {
|
||||
{ kind = "upright", x = { 2, 13 }, top = { 0, 2 },
|
||||
facade = { 3, 10 }, depth = 4 }, -- the monitor
|
||||
{ kind = "flat", x = { 1, 13 }, rows = { 11, 14 } }, -- keyboard
|
||||
{ kind = "upright", x = { 14, 21 }, top = { 0, 3 },
|
||||
facade = { 4, 10 }, depth = 6 }, -- the tower
|
||||
{ kind = "flat", x = { 14, 21 }, rows = { 11, 14 } }, -- keys+mouse
|
||||
{ kind = "flat", x = { 22, 30 }, rows = { 1, 14 } }, -- the paper
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -307,11 +307,154 @@ end
|
||||
|
||||
-- ----------------------------------------------------------------- build --
|
||||
|
||||
-- A desk with separately-classified objects on it (a template's `parts`
|
||||
-- list): the methodology's region classification at part granularity.
|
||||
-- Upright parts anchor their drawn bottom row to the desk's top plane
|
||||
-- and wear their own drawn tops as lids; flat parts (a keyboard, a
|
||||
-- sheet of paper) lie one voxel proud at drawn row = depth row -- the
|
||||
-- same 1:1 the tabletop itself is drawn with, so an object's height ON
|
||||
-- the drawing is its position ON the desk. The desk is the lab-table
|
||||
-- slab + base; its lid is the one synthesized surface in the model
|
||||
-- (the objects cover every drawn pixel of the tabletop), continued
|
||||
-- from the sibling tables' pattern in the drawing's own shades.
|
||||
-- tools/building_voxels.py `build_desk_set` is the reference twin.
|
||||
local function deskSetModel(sp, pr, t)
|
||||
local W, H, D = sp.W, sp.H, pr.D
|
||||
local ground = pr.ground
|
||||
local col, inside = sp.col, sp.inside
|
||||
local vox = {}
|
||||
local function key(x, y, z) return (y * D + z) * W + x end
|
||||
local function put(x, y, z, i) vox[key(x, y, z)] = i end
|
||||
|
||||
-- de-outline walk bounded to the part, so a part's side faces show
|
||||
-- its own material and never the neighbour's (the sprite-wide walk
|
||||
-- the facade path uses would cross the black seam between units)
|
||||
local function interiorAt(sx, sy, lo, hi)
|
||||
local i = sy * W + sx
|
||||
if col[i] ~= BLACK then return sx end
|
||||
local step = sx < math.floor((lo + hi) / 2) and 1 or -1
|
||||
for d = 1, 3 do
|
||||
local nx = sx + step * d
|
||||
if nx >= lo and nx <= hi then
|
||||
local ni = sy * W + nx
|
||||
if inside[ni] and col[ni] ~= BLACK then return nx end
|
||||
end
|
||||
end
|
||||
return sx
|
||||
end
|
||||
|
||||
local f0, f1 = t.desk.fascia[1], t.desk.fascia[2]
|
||||
local b0, b1 = t.desk.base[1], t.desk.base[2]
|
||||
local plane = (b1 - b0 + 1) + (f1 - f0 + 1)
|
||||
|
||||
-- the base band, extruded exactly like every lab table's
|
||||
for sy = b0, b1 do
|
||||
Budget.tick()
|
||||
local y = ground - 1 - sy
|
||||
for sx = 0, W - 1 do
|
||||
if inside[sy * W + sx] then
|
||||
local ix = interiorAt(sx, sy, 0, W - 1)
|
||||
for z = 0, D - 1 do
|
||||
local px = (z == 0 or z == D - 1) and sx or ix
|
||||
put(sx, y, z, sy * W + px)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for i in pairs(pr.recess) do
|
||||
local sy = math.floor(i / W)
|
||||
if sy >= b0 and sy <= b1 then
|
||||
vox[key(i % W, ground - 1 - sy, D - 1)] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- the slab: fascia rows wrap every side; the lid continues the
|
||||
-- sibling tables' top -- black rim, white highlight courses along
|
||||
-- the north and west, grey field
|
||||
for sy = f0, f1 do
|
||||
Budget.tick()
|
||||
local y = plane - 1 - (sy - f0)
|
||||
for sx = 0, W - 1 do
|
||||
for z = 0, D - 1 do put(sx, y, z, sy * W + sx) end
|
||||
end
|
||||
end
|
||||
for sx = 0, W - 1 do
|
||||
for z = 0, D - 1 do
|
||||
local shade = GREY
|
||||
if sx == 0 or sx == W - 1 or z == 0 or z == D - 1 then
|
||||
shade = BLACK
|
||||
elseif sx == 1 or z == 1 then
|
||||
shade = WHITE
|
||||
end
|
||||
put(sx, plane - 1, z, pr.shadeTexel[shade])
|
||||
end
|
||||
end
|
||||
|
||||
local ytop = plane
|
||||
for _, p in ipairs(t.parts) do
|
||||
Budget.tick()
|
||||
local x0, x1 = p.x[1], p.x[2]
|
||||
if p.kind == "flat" then
|
||||
for sy = p.rows[1], p.rows[2] do
|
||||
if sy >= 0 and sy < D then
|
||||
for sx = x0, x1 do
|
||||
if inside[sy * W + sx] then put(sx, plane, sy, sy * W + sx) end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local tr0, tr1 = p.top[1], p.top[2]
|
||||
local fr0, fr1 = p.facade[1], p.facade[2]
|
||||
local pd = p.depth
|
||||
local ytp = plane + (fr1 - fr0)
|
||||
if ytp > ytop then ytop = ytp end
|
||||
for sx = x0, x1 do
|
||||
-- the lid: the part's drawn top laid across its depth from the
|
||||
-- back, last row continuing forward; the front lid row is the
|
||||
-- facade's own top row -- the drawn front-top edge
|
||||
for z = 0, pd - 1 do
|
||||
local front = z == pd - 1
|
||||
local sy = front and fr0 or math.min(tr0 + z, tr1)
|
||||
while sy <= tr1 and not inside[sy * W + sx] do sy = sy + 1 end
|
||||
local ok = sy <= tr1 or (front and inside[fr0 * W + sx])
|
||||
if ok then
|
||||
put(sx, ytp, z, (front and fr0 or sy) * W + sx)
|
||||
end
|
||||
end
|
||||
-- the body: facade rows anchored to the desk's top plane
|
||||
for sy = fr0 + 1, fr1 do
|
||||
local y = plane + (fr1 - sy)
|
||||
local i = sy * W + sx
|
||||
if inside[i] then
|
||||
local ix = interiorAt(sx, sy, x0, x1)
|
||||
for z = 0, pd - 1 do
|
||||
if z == pd - 1 then
|
||||
if not pr.recess[i] then put(sx, y, z, i) end
|
||||
elseif z == 0 then
|
||||
put(sx, y, z, i)
|
||||
else
|
||||
put(sx, y, z, sy * W + ix)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return { at = function(x, y, z)
|
||||
if x < 0 or x >= W or y < 0 or z < 0 or z >= D then return nil end
|
||||
return vox[key(x, y, z)]
|
||||
end,
|
||||
W = W, ytop = ytop, zmin = 0, zmax = D - 1 }
|
||||
end
|
||||
|
||||
-- The voxel model as a lookup: `at(x, y, z)` is the index of the sprite
|
||||
-- pixel that voxel wears, or nil. Build ORDER is expressed as lookup
|
||||
-- order -- roof first, so it overwrites the walls it intersects, and walls
|
||||
-- are trimmed to its underside so nothing pokes through the surface.
|
||||
local function model(sp, pr, t)
|
||||
if t.parts then return deskSetModel(sp, pr, t) end
|
||||
local W, H, D = sp.W, sp.H, pr.D
|
||||
local slab, roofRows = t.slab, t.roofRows
|
||||
local top, ytop, ground = pr.top, pr.ytop, pr.ground
|
||||
|
||||
+184
-15
@@ -569,15 +569,21 @@ TEMPLATES = {
|
||||
roof_rows=19, roof_back=16, roof_front=0, roof_cycle=(2, 13),
|
||||
slab=3, front_eave=0, ledge=None, tileset="gym", depth=2,
|
||||
),
|
||||
# F02: the computer bank on Oak's lab's west table -- and the Hall
|
||||
# of Fame's recording machine, the same drawing on the GYM atlas
|
||||
# (one placement each; both registered in voxel_heights). The one
|
||||
# FACADE-ONLY template: rows 0-14 are machines drawn face-on over
|
||||
# the lab-table fascia and base bands, nothing is drawn from above,
|
||||
# so roof_rows=0 and the whole drawing extrudes -- the house facade
|
||||
# treatment with no roof band. The recess pass turns every framed
|
||||
# pane (the monitor, its keys, the right cabinet's inset face) into
|
||||
# relief on its own.
|
||||
# F02: the computer desk in Oak's lab -- and the Hall of Fame's
|
||||
# recording machine, the same drawing on the GYM atlas (one
|
||||
# placement each; both registered in voxel_heights). The one
|
||||
# DESK-SET template: the methodology's region classification at
|
||||
# part granularity. The desk is the sibling lab table (fascia rows
|
||||
# 16-18, base 19-21); on it stand a monitor over its keyboard
|
||||
# (left), a computer tower over a keyboard and mouse (middle), and
|
||||
# a sheet of paper LYING FLAT (right). Upright parts anchor their
|
||||
# drawn bottom row to the desk's top plane and wear their own drawn
|
||||
# tops as lids; flat parts lie one voxel proud with drawn row =
|
||||
# depth row -- the same 1:1 the tabletop itself is drawn with, so
|
||||
# an object's height ON the drawing is its position ON the desk.
|
||||
# The desk's own top is the one synthesized surface (the objects
|
||||
# cover every pixel of it), continued from the sibling tables'
|
||||
# pattern in the drawing's own shades.
|
||||
"lab_computers": dict(
|
||||
tiles=[
|
||||
[91, 92, 93, 94],
|
||||
@@ -586,6 +592,16 @@ TEMPLATES = {
|
||||
],
|
||||
roof_rows=0, roof_back=0, roof_front=0, roof_cycle=(0, 0),
|
||||
slab=0, front_eave=0, ledge=None, tileset="gym", depth=2,
|
||||
desk=dict(fascia=(16, 18), base=(19, 21)),
|
||||
parts=[
|
||||
dict(kind="upright", x=(2, 13), top=(0, 2), facade=(3, 10),
|
||||
depth=4), # the monitor
|
||||
dict(kind="flat", x=(1, 13), rows=(11, 14)), # its keyboard
|
||||
dict(kind="upright", x=(14, 21), top=(0, 3), facade=(4, 10),
|
||||
depth=6), # the tower
|
||||
dict(kind="flat", x=(14, 21), rows=(11, 14)), # keys + mouse
|
||||
dict(kind="flat", x=(22, 30), rows=(1, 14)), # the paper
|
||||
],
|
||||
),
|
||||
# F03: the empty north table beside it -- the starter table's band
|
||||
# table verbatim on a grid two tiles narrower (one placement).
|
||||
@@ -741,10 +757,122 @@ def profile(sp, t):
|
||||
|
||||
|
||||
# --------------------------------------------------------------- stage 3 --
|
||||
def build_desk_set(sp, pr, t):
|
||||
"""A desk with separately-classified objects on it (the `parts` list):
|
||||
upright parts stand on the desk's top plane wearing their own drawn
|
||||
tops as lids, flat parts lie one voxel proud at drawn row = depth row,
|
||||
and the desk itself is the lab-table slab + base with a synthesized
|
||||
lid (the objects cover every drawn pixel of the tabletop)."""
|
||||
W, H, D = pr["W"], pr["H"], pr["D"]
|
||||
inside = pr["inside"]
|
||||
col, src = sp["col"], sp["src"]
|
||||
ground = pr["ground"]
|
||||
vox = {}
|
||||
|
||||
def put(x, y, z, sx, sy):
|
||||
vox[(x, y, z)] = (col[sy][sx], src[sy][sx])
|
||||
|
||||
shade_px = {}
|
||||
for sy in range(H):
|
||||
for sx in range(W):
|
||||
if inside(sx, sy):
|
||||
shade_px.setdefault(col[sy][sx], (sx, sy))
|
||||
|
||||
def interior(sx, sy, lo, hi):
|
||||
if col[sy][sx] != BLACK:
|
||||
return sx
|
||||
step = 1 if sx < (lo + hi) // 2 else -1
|
||||
for d in range(1, 4):
|
||||
nx = sx + step * d
|
||||
if lo <= nx <= hi and inside(nx, sy) and col[sy][nx] != BLACK:
|
||||
return nx
|
||||
return sx
|
||||
|
||||
f0, f1 = t["desk"]["fascia"]
|
||||
b0, b1 = t["desk"]["base"]
|
||||
plane = (b1 - b0 + 1) + (f1 - f0 + 1) # the desk's top plane
|
||||
|
||||
# the base band, extruded exactly like every lab table's
|
||||
for sy in range(b0, b1 + 1):
|
||||
y = ground - 1 - sy
|
||||
for sx in range(W):
|
||||
if not inside(sx, sy):
|
||||
continue
|
||||
ix = interior(sx, sy, 0, W - 1)
|
||||
for z in range(D):
|
||||
put(sx, y, z, sx if z in (0, D - 1) else ix, sy)
|
||||
for sx, sy in pr["recess"]:
|
||||
if b0 <= sy <= b1:
|
||||
vox.pop((sx, ground - 1 - sy, D - 1), None)
|
||||
|
||||
# the slab: the fascia rows wrap every side; the lid is the one
|
||||
# synthesized surface in the model -- the drawing never paints the
|
||||
# tabletop (its objects cover it), so the lid continues the sibling
|
||||
# tables' pattern in the drawing's own shades: black rim, white
|
||||
# highlight courses along the north and west, grey field
|
||||
for i, sy in enumerate(range(f0, f1 + 1)):
|
||||
y = plane - 1 - i
|
||||
for sx in range(W):
|
||||
for z in range(D):
|
||||
put(sx, y, z, sx, sy)
|
||||
for sx in range(W):
|
||||
for z in range(D):
|
||||
if sx in (0, W - 1) or z in (0, D - 1):
|
||||
shade = BLACK
|
||||
elif sx == 1 or z == 1:
|
||||
shade = WHITE
|
||||
else:
|
||||
shade = GREY
|
||||
px = shade_px.get(shade) or shade_px[BLACK]
|
||||
put(sx, plane - 1, z, px[0], px[1])
|
||||
|
||||
for p in t["parts"]:
|
||||
x0, x1 = p["x"]
|
||||
if p["kind"] == "flat":
|
||||
r0, r1 = p["rows"]
|
||||
for sy in range(r0, r1 + 1):
|
||||
if not 0 <= sy < D:
|
||||
continue
|
||||
for sx in range(x0, x1 + 1):
|
||||
if inside(sx, sy):
|
||||
put(sx, plane, sy, sx, sy)
|
||||
continue
|
||||
tr0, tr1 = p["top"]
|
||||
fr0, fr1 = p["facade"]
|
||||
pd = p["depth"]
|
||||
ytp = plane + (fr1 - fr0)
|
||||
for sx in range(x0, x1 + 1):
|
||||
# the lid: the part's drawn top laid across its depth from
|
||||
# the back, last row continuing forward; the front lid row
|
||||
# is the facade's own top row -- the drawn front-top edge
|
||||
for z in range(pd):
|
||||
sy = fr0 if z == pd - 1 else min(tr0 + z, tr1)
|
||||
while sy <= tr1 and not inside(sx, sy):
|
||||
sy += 1
|
||||
if sy > tr1 and not (z == pd - 1 and inside(sx, fr0)):
|
||||
continue
|
||||
put(sx, ytp, z, sx, fr0 if z == pd - 1 else sy)
|
||||
# the body: facade rows anchored to the desk's top plane
|
||||
for sy in range(fr0 + 1, fr1 + 1):
|
||||
y = plane + (fr1 - sy)
|
||||
if not inside(sx, sy):
|
||||
continue
|
||||
ix = interior(sx, sy, x0, x1)
|
||||
for z in range(pd):
|
||||
if z == pd - 1:
|
||||
if (sx, sy) not in pr["recess"]:
|
||||
put(sx, y, z, sx, sy)
|
||||
else:
|
||||
put(sx, y, z, sx if z == 0 else ix, sy)
|
||||
return vox
|
||||
|
||||
|
||||
def build(sp, pr, t):
|
||||
"""The voxel model. Order is load-bearing: walls, ledge, recesses, then
|
||||
the roof solid overwrites what it intersects and the walls are trimmed
|
||||
to the roof's underside."""
|
||||
if t.get("parts"):
|
||||
return build_desk_set(sp, pr, t)
|
||||
W, H, D = pr["W"], pr["H"], pr["D"]
|
||||
inside, top, ytop = pr["inside"], pr["top"], pr["ytop"]
|
||||
col, src = sp["col"], sp["src"]
|
||||
@@ -869,12 +997,13 @@ def verify(vox, sp, pr, t):
|
||||
for (x, y, z), _ in vox.items():
|
||||
assert y <= T(x), f"voxel pokes through the roof at {x},{y},{z}"
|
||||
|
||||
# A facade-only template (roof_rows == 0: the lab computer bank) has
|
||||
# no roof band, so there is no surface to hold level or slope and no
|
||||
# coverage to demand of it; the poke-through assert above and the
|
||||
# facade asserts below are what it answers to. Everything with a roof
|
||||
# band answers the full set.
|
||||
if t["roof_rows"] == 0:
|
||||
# A desk set answers its own asserts; a facade-only template (roof_rows
|
||||
# == 0) has no roof band, so there is no surface to hold level or slope
|
||||
# and no coverage to demand of it; everything with a roof band answers
|
||||
# the full set.
|
||||
if t.get("parts"):
|
||||
verify_desk_set(vox, pr, t)
|
||||
elif t["roof_rows"] == 0:
|
||||
# its one geometric intent: a straight extrusion, so each column
|
||||
# of the drawing is solid from its lowest voxel to its top. NOT
|
||||
# from the ground -- the drawing's base band is inset like every
|
||||
@@ -899,6 +1028,46 @@ def verify(vox, sp, pr, t):
|
||||
return shell
|
||||
|
||||
|
||||
def verify_desk_set(vox, pr, t):
|
||||
W, D = pr["W"], pr["D"]
|
||||
f0, f1 = t["desk"]["fascia"]
|
||||
b0, b1 = t["desk"]["base"]
|
||||
plane = (b1 - b0 + 1) + (f1 - f0 + 1)
|
||||
|
||||
# the slab is a full solid under everything on it
|
||||
for x in range(W):
|
||||
for z in range(D):
|
||||
for y in range(b1 - b0 + 1, plane):
|
||||
assert (x, y, z) in vox, f"slab hole at {x},{y},{z}"
|
||||
|
||||
# each part stands where authored -- upright bodies solid from the
|
||||
# desk to their own drawn top (bar the front layer, whose panes
|
||||
# sink) -- and nothing stands anywhere else
|
||||
tops = {}
|
||||
for p in t["parts"]:
|
||||
x0, x1 = p["x"]
|
||||
if p["kind"] == "flat":
|
||||
r0, r1 = p["rows"]
|
||||
for x in range(x0, x1 + 1):
|
||||
for z in range(max(r0, 0), min(r1, D - 1) + 1):
|
||||
tops[(x, z)] = max(tops.get((x, z), 0), plane)
|
||||
else:
|
||||
fr0, fr1 = p["facade"]
|
||||
ytp = plane + (fr1 - fr0)
|
||||
for x in range(x0, x1 + 1):
|
||||
for z in range(p["depth"]):
|
||||
tops[(x, z)] = max(tops.get((x, z), 0), ytp)
|
||||
if z == p["depth"] - 1:
|
||||
continue
|
||||
ys = [y for y in range(plane, ytp + 1)
|
||||
if (x, y, z) in vox]
|
||||
assert ys == list(range(ys[0], ys[0] + len(ys))) \
|
||||
if ys else True, f"part column hole at {x},{z}"
|
||||
for (x, y, z) in vox:
|
||||
assert y <= tops.get((x, z), plane - 1), \
|
||||
f"voxel above its part at {x},{y},{z}"
|
||||
|
||||
|
||||
def verify_roof(vox, pr, t):
|
||||
W, H, D = pr["W"], pr["H"], pr["D"]
|
||||
ytop, top, slab = pr["ytop"], pr["top"], t["slab"]
|
||||
|
||||
Reference in New Issue
Block a user