Skip to main content

Module chunk_mesh

Module chunk_mesh 

Source
Expand description

Reference mesh for the per-chunk triangular grid (Phase 2, CEL-62).

§Canonical vertex order

Vertices are enumerated in row-major order by (i, j) where:

  • i = row index (the wb axis), 0 ≤ i ≤ res
  • j = column index (the wc axis), 0 ≤ j ≤ res − i

The linear index L for vertex at (i, j) is:

L(i, j) = i*(2*res + 3 − i)/2 + j

(Equivalently: L(i, j) = i*(res+1) − i*(i−1)/2 + j.)

Row i starts at L_row(i) = i*(2*res + 3 − i)/2, with res+1−i vertices.

Special corner vertices:

  • L = 0(i,j) = (0,0) → corner A: wa=1, wb=0, wc=0
  • L = res(i,j) = (0,res) → corner C: wa=0, wb=0, wc=1
  • L = verts_per_chunk(res)−1(i,j) = (res,0) → corner B: wa=0, wb=1, wc=0

ChunkRealize.slang (Task 7) must enumerate local vertices in this same order and decode L using the same formula.

§Vertex storage convention

Each vertex is stored as [wa, wb, wc] — the full barycentric triplet (wa+wb+wc=1):

wa = (res − i − j) as f32 / res as f32
wb = i as f32 / res as f32
wc = j as f32 / res as f32

§Triangle winding

Triangles are output in two interleaved passes for each cell (i, j) with i+j < res:

  1. Upward triangle: L(i,j), L(i,j+1), L(i+1,j) — always present.
  2. Downward triangle (only when i+j+1 < res): L(i+1,j), L(i,j+1), L(i+1,j+1).

Both share the same (uniform) winding, ordered so the OUTWARD surface is front under render_mode cull_back in terrain_chunk.gdshader.

§Perimeter skirts (Phase 3 crack fix)

Adjacent chunks at different quadtree depths tessellate their shared edge at different resolutions → T-junctions where heights differ → cracks. To hide them we append a skirt: a ring of extra vertices at the same edge positions as the interior perimeter, but pushed radially inward (toward the planet centre) by a per-chunk depth, connected to the interior edge by triangles. A crack then shows skirt terrain instead of a hole.

§Skirt vertex numbering (mirrored EXACTLY in ChunkRealize.slang)

Interior verts occupy L ∈ [0, interior_verts_per_chunk(res)). Skirt verts are appended at L = interior + s, s ∈ [0, 3*(res+1)), with edge = s / (res+1) and t = s % (res+1) (the along-edge position 0..=res):

  • edge 0 (A→B): interior lattice point (i,j) = (t, 0)
  • edge 1 (B→C): (i,j) = (res−t, t)
  • edge 2 (C→A): (i,j) = (0, res−t)

A skirt vert stores the SAME barycentric as its interior edge vert (so its TEX_UV samples the same atlas texel and it shades like the edge); the realize shader drops its position inward. Corners are duplicated (each of the 3 edges owns its own ring), so skirt vertices are always DISTINCT pool entries from the interior edge verts they mirror.

§Skirt triangles

For each edge and each of the res segments k (interior verts E_k, E_{k+1}; skirt verts S_k, S_{k+1}) two triangles T1 = (E_k, E_{k+1}, S_{k+1}), T2 = (E_k, S_{k+1}, S_k). The interior triangle adjacent to every perimeter segment traverses the boundary edge as E_{k+1} → E_k; the skirt traverses it the opposite way (E_k → E_{k+1}), so the skirt is consistently oriented with the interior — i.e. the same front/back class under cull_back.

Functions§

chunk_grid
Generate the triangular grid vertices and triangle indices for a chunk at resolution res.
reference_chunk_mesh
Build a Godot ArrayMesh reference chunk at resolution res.