Add test hill

This commit is contained in:
2026-06-30 18:21:46 -05:00
parent a6f449bb93
commit 6a403e6caf
6 changed files with 319 additions and 1248 deletions
+56 -17
View File
@@ -64,8 +64,16 @@ CHUNK_MESH_NAME_MAX = 64
TILE_SIZE = 4
VERTEX_SIZE = 20
TILE_SHAPE_NULL = 0
TILE_SHAPE_GROUND = 1
TILE_SHAPE_NULL = 0
TILE_SHAPE_GROUND = 1
TILE_SHAPE_RAMP_NORTH = 2
TILE_SHAPE_RAMP_EAST = 3
TILE_SHAPE_RAMP_SOUTH = 4
TILE_SHAPE_RAMP_WEST = 5
TILE_SHAPE_RAMP_NORTHEAST = 6
TILE_SHAPE_RAMP_NORTHWEST = 7
TILE_SHAPE_RAMP_SOUTHEAST = 8
TILE_SHAPE_RAMP_SOUTHWEST = 9
FILE_MAGIC = b'DCF'
DMF_MAGIC = b'DMF\x00'
@@ -147,8 +155,42 @@ def write_v3(dcf_path, tiles, mesh_names, mesh_offsets=None):
# JSON -> DCF + DMF
# ---------------------------------------------------------------------------
def _tile_quad(u0, u1, v0, v1, fx, fy, sw_z, se_z, ne_z, nw_z):
"""Six vertices (2 CCW triangles) for a quad with per-corner Z heights.
Corner order: SW=(fx,fy), SE=(fx+1,fy), NE=(fx+1,fy+1), NW=(fx,fy+1).
NORTH=+Y, EAST=+X (matches entityDirGetRelative)."""
verts = [
(u0, v0, fx, fy, sw_z),
(u1, v0, fx+1, fy, se_z),
(u1, v1, fx+1, fy+1, ne_z),
(u0, v0, fx, fy, sw_z),
(u1, v1, fx+1, fy+1, ne_z),
(u0, v1, fx, fy+1, nw_z),
]
buf = bytearray()
for v in verts:
buf += struct.pack('<5f', *v)
return bytes(buf)
# Per-shape corner heights as (sw, se, ne, nw) offsets from tile base Z.
# NORTH=+Y, EAST=+X. Cardinal ramps: low face at 0, high face at 1.
# Diagonal ramps: opposite corner at 0/1, adjacent corners at 0.5.
_RAMP_CORNERS = {
TILE_SHAPE_GROUND: (0.0, 0.0, 0.0, 0.0),
TILE_SHAPE_RAMP_NORTH: (0.0, 0.0, 1.0, 1.0), # south=low, north=high
TILE_SHAPE_RAMP_SOUTH: (1.0, 1.0, 0.0, 0.0), # south=high, north=low
TILE_SHAPE_RAMP_EAST: (0.0, 1.0, 1.0, 0.0), # west=low, east=high
TILE_SHAPE_RAMP_WEST: (1.0, 0.0, 0.0, 1.0), # west=high, east=low
TILE_SHAPE_RAMP_NORTHEAST: (0.0, 0.0, 1.0, 0.0), # only NE raised
TILE_SHAPE_RAMP_NORTHWEST: (0.0, 0.0, 0.0, 1.0), # only NW raised
TILE_SHAPE_RAMP_SOUTHEAST: (0.0, 1.0, 0.0, 0.0), # only SE raised
TILE_SHAPE_RAMP_SOUTHWEST: (1.0, 0.0, 0.0, 0.0), # only SW raised
}
def build_terrain_verts(tiles_bytes):
"""Generate top-face quads for every TILE_SHAPE_GROUND tile."""
"""Generate quads for every non-null tile, shaped to match tile type."""
buf = bytearray()
for z in range(CHUNK_DEPTH):
for y in range(CHUNK_HEIGHT):
@@ -157,22 +199,19 @@ def build_terrain_verts(tiles_bytes):
tile_type = struct.unpack_from(
'<I', tiles_bytes, idx * TILE_SIZE
)[0]
if tile_type != TILE_SHAPE_GROUND:
corners = _RAMP_CORNERS.get(tile_type)
if corners is None:
continue
fx, fy, fz = float(x), float(y), float(z)
uv_u0 = x / CHUNK_WIDTH
uv_u1 = (x + 1) / CHUNK_WIDTH
uv_v0 = y / CHUNK_HEIGHT
uv_v1 = (y + 1) / CHUNK_HEIGHT
for v in [
(uv_u0, uv_v0, fx, fy, fz),
(uv_u1, uv_v0, fx+1, fy, fz),
(uv_u1, uv_v1, fx+1, fy+1, fz),
(uv_u0, uv_v0, fx, fy, fz),
(uv_u1, uv_v1, fx+1, fy+1, fz),
(uv_u0, uv_v1, fx, fy+1, fz),
]:
buf += struct.pack('<5f', *v)
u0 = x / CHUNK_WIDTH
u1 = (x + 1) / CHUNK_WIDTH
v0 = y / CHUNK_HEIGHT
v1 = (y + 1) / CHUNK_HEIGHT
sw, se, ne, nw = corners
buf += _tile_quad(
u0, u1, v0, v1, fx, fy,
fz + sw, fz + se, fz + ne, fz + nw
)
return bytes(buf)