mirror of
https://github.com/DramaticShape/DramaticShapeVoxelMod.git
synced 2026-08-12 08:11:11 +02:00
fix shoreline slits beside claimed tiles and dropped edge-row facades
Two voxel-mode holes, both in ChunkMesher's keep/emit rules: 1. A tile claimed by a standing object (building footprint, sign standee, pond bushes) painted only its flat synthesized ground and never emitted side faces, so beside recessed water the 2px step was an open slit into the sky. The skip branch now emits the same below-ground side bands ordinary ground does, cut from the synthesized ground's art. 2. A profiled building whose front row is the map's last tile row has its facade exactly on the shared boundary plane (Saffron's row houses seen from Route 6), where the strict overBody test and the closed neighbour mask dropped it. Outward-facing quads on the body's boundary planes are now kept, told apart from ring scraps -- the thing the mask exists to kill -- by their winding.
This commit is contained in:
@@ -1,5 +1,33 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Fixed
|
||||
|
||||
- **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