mirror of
https://github.com/DramaticShape/DramaticShapeVoxelMod.git
synced 2026-08-12 18:20:51 +02:00
Merge branch 'worktree-dramatic-shape-water-facades' into 20260726_various_fixes
# Conflicts: # CHANGELOG.md
This commit is contained in:
@@ -104,6 +104,30 @@
|
||||
mod's own fallback chain and skips toggle entries in the placement
|
||||
census.
|
||||
|
||||
- **The shoreline no longer opens into the sky beside buildings and
|
||||
signs.** Water recesses 2px below the ground, and the ground tile beside
|
||||
it closes the step with a small below-ground side band -- but a tile
|
||||
CLAIMED by a standing object (a building footprint, a sign standee, the
|
||||
bushes ringing Fuchsia's ponds) only painted its synthesized flat ground
|
||||
and never emitted sides. Along every stretch where such a tile met
|
||||
water, the two-pixel step was an open slit straight through to the sky
|
||||
behind the mesh. The skip branch now emits the same below-ground bands
|
||||
ordinary ground does, cut from the synthesized ground's own art, so the
|
||||
shoreline lip is continuous whatever stands on the bank.
|
||||
|
||||
- **Edge-row buildings keep their facades.** The south wall of Saffron's
|
||||
row houses -- profiled buildings whose front row is the map's last tile
|
||||
row -- lies exactly on the boundary plane shared with Route 6, and the
|
||||
prebuilt-quad keep rules dropped it: the strict body test excludes the
|
||||
plane, and the closed neighbour mask (which exists to kill ring scraps
|
||||
whose rects sit exactly on that line) swallowed what was left, so from
|
||||
Route 6 the houses stood hollow. The two cases are geometrically
|
||||
identical degenerate rects, but they FACE opposite ways: a face pointing
|
||||
away from the body is this map's own facade and nothing in the
|
||||
neighbour will ever draw that plane, while a face pointing into the
|
||||
body is the scrap the mask is for. The mesher now reads the winding and
|
||||
keeps outward faces on the body's boundary planes, on all four edges.
|
||||
|
||||
## 1.0.3
|
||||
|
||||
### Added
|
||||
|
||||
+56
-2
@@ -430,7 +430,36 @@ local function runGeometry(map, bodyOnly, masks, sink)
|
||||
if s and S.skip[k] then
|
||||
-- an object stands here; paint its synthesized ground and let the
|
||||
-- prebuilt prism quads (appended below) carry the art
|
||||
if S.ground[k] then topQuad(tx * 8, ty * 8, 0, S.ground[k], 1) end
|
||||
local g = S.ground[k]
|
||||
if g then
|
||||
topQuad(tx * 8, ty * 8, 0, g, 1)
|
||||
-- the claimed tile is still ground at height 0, and water next
|
||||
-- door still recesses below it: without the same below-ground
|
||||
-- side bands ordinary ground emits, the two-pixel shoreline
|
||||
-- face is a slit into the sky behind the mesh -- which is
|
||||
-- exactly what a building plot or a sign standing at the
|
||||
-- waterline showed. Same bands, cut from the synthesized
|
||||
-- ground's own art
|
||||
for _, side in ipairs(SIDES) do
|
||||
local nh = heightAt(tx + side[1], ty + side[2])
|
||||
if nh < 0 then
|
||||
local d = side[3]
|
||||
local lat = LATERAL[d]
|
||||
local hl = lat and heightAt(tx + lat[1], ty + lat[2]) or 0
|
||||
local hr = lat and heightAt(tx + lat[3], ty + lat[4]) or 0
|
||||
for band = math.floor(nh / 8), -1 do
|
||||
local y0 = math.max(nh, band * 8)
|
||||
local y1 = math.min(0, band * 8 + 8)
|
||||
if y1 > y0 then
|
||||
sideQuad(d, tx * 8, ty * 8, y0, y1, g,
|
||||
(band * 8 + 8) - y1, (band * 8 + 8) - y0,
|
||||
sideShades(hl, hr, y0, y1, y0 <= nh,
|
||||
Voxel3D.FACE_SHADE[d]))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif s then
|
||||
local run = S.runs[k]
|
||||
local h = run and run.h or s.h
|
||||
@@ -610,6 +639,31 @@ local function runGeometry(map, bodyOnly, masks, sink)
|
||||
return overBody or not maskedClosed(x0, z0, x1, z1)
|
||||
end
|
||||
|
||||
-- A face lying EXACTLY on a body boundary plane is ambiguous to the
|
||||
-- rect tests above: a body structure's outward facade (a Saffron row
|
||||
-- house whose front row is the map's last row, its south wall on the
|
||||
-- shared plane with Route 6) and the inward face of a ring scrap
|
||||
-- occupy the same degenerate rect, and the strict overBody plus the
|
||||
-- closed mask dropped BOTH -- which is why those facades were missing.
|
||||
-- The winding tells them apart: a face pointing AWAY from the body
|
||||
-- belongs to this map's own edge-row structure and nothing in the
|
||||
-- neighbour will ever draw that plane, so it stays; a face pointing
|
||||
-- INTO the body is the scrap the mask rules exist to kill, and falls
|
||||
-- through to them.
|
||||
local function outwardOnEdge(q, x0, z0, x1, z1)
|
||||
if z0 == z1 and (z0 == 0 or z0 == bh) and x1 > 0 and x0 < bw then
|
||||
local nz = (q[2][1] - q[1][1]) * (q[3][2] - q[1][2])
|
||||
- (q[2][2] - q[1][2]) * (q[3][1] - q[1][1])
|
||||
return (z0 == bh and nz > 0) or (z0 == 0 and nz < 0)
|
||||
end
|
||||
if x0 == x1 and (x0 == 0 or x0 == bw) and z1 > 0 and z0 < bh then
|
||||
local nx = (q[2][2] - q[1][2]) * (q[3][3] - q[1][3])
|
||||
- (q[2][3] - q[1][3]) * (q[3][2] - q[1][2])
|
||||
return (x0 == bw and nx > 0) or (x0 == 0 and nx < 0)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local scUV = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }
|
||||
local function quadUV(q)
|
||||
if q.uv then return q.uv end
|
||||
@@ -625,7 +679,7 @@ local function runGeometry(map, bodyOnly, masks, sink)
|
||||
local x1 = math.max(q[1][1], q[2][1], q[3][1], q[4][1])
|
||||
local z0 = math.min(q[1][3], q[2][3], q[3][3], q[4][3])
|
||||
local z1 = math.max(q[1][3], q[2][3], q[3][3], q[4][3])
|
||||
if keepQuad(x0, z0, x1, z1) then
|
||||
if outwardOnEdge(q, x0, z0, x1, z1) or keepQuad(x0, z0, x1, z1) then
|
||||
push({ q[1], q[2], q[3], q[4] }, quadUV(q), groundShades(q, q.shade))
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user