sourceextensions/scene/demos/Voxels.xtl
1⍝# Voxels.xtl -- voxel chunks as arrays, shared by the voxels-* demos
2⍝# (docs/voxels.md). A chunk is a 16 by 16 by 16 array of block numbers,
3⍝# indexed x (east), y (up), z (south); 0 is air.
4⍝# Import: "vx:" u_se< "Voxels"
5⍝# (Not voxels.xtl: on a case-insensitive file system a demo of that name
6⍝# would be this file -- ask E8.)
7
8⍝## Chunks
9
10⍝# the side of a chunk
11ˡn ← 16
12⍝# the cells of a chunk, 16 cubed
13ˡcells ← 4096
14
15⍝# block 0: air
16ˡair ← 0
17⍝# block 1: stone, below the dirt
18ˡstone ← 1
19⍝# block 2: dirt, three below the grass
20ˡdirt ← 2
21⍝# block 3: grass, on top
22ˡgrass ← 3
23⍝# block 4: sand, where grass would be at or below the water
24ˡsand ← 4
25⍝# block 5: water, filling air below its level (not solid)
26ˡwater ← 5
27⍝# block 6: wood, a tree's trunk
28ˡwood ← 6
29⍝# block 7: leaves, a tree's crown
30ˡleaves ← 7
31⍝# the blocks' names, in their order
32⍝# >> "vx:" u_se< "Voxels"
33⍝# >> vx:names
34⍝# air stone dirt grass sand water wood leaves
35ˡnames ← "air stone dirt grass sand water wood leaves"
36⍝# a character for each block when a chunk is printed, air first:
37⍝# stone #, dirt %, grass ", sand :, water ~, wood |, leaves *
38ˡglyphs ← " #%\":~|*"
39
40i ← (r̲ange 4096) − 1
41⍝# every cell's x (east), as a vector in the chunk's order (x slowest)
42⍝# >> "vx:" u_se< "Voxels"
43⍝# >> 18 t_ake vx:xs
44⍝# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
45ˡxs ← i d̲iv 256
46⍝# every cell's y (up), in the chunk's order
47ˡys ← (i d̲iv 16) m̲od 16
48⍝# every cell's z (south), in the chunk's order (z fastest)
49⍝# >> "vx:" u_se< "Voxels"
50⍝# >> 18 t_ake vx:zs
51⍝# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1
52ˡzs ← i m̲od 16
53
54⍝# vx:h_ills phase: a 16 by 16 height field (x by z), rolling hills of
55⍝# heights 3 to 12; the phase shifts them
56ˡh̲ills ← { p →
57 x ← f̲loat (r̲ange 16) − 1
58 a ← 2.5 × s̲in p + x ÷ 2.5
59 b ← 2.0 × c̲os p + x ÷ 3.0
60 f̲loor 7.5 + a '+ t̲able b
61}
62
63⍝# vx:c_hunk h: the chunk on a height field h (x by z): grass on top,
64⍝# three of dirt, stone below; water fills air below 7, and sand
65⍝# replaces grass at or below it; one tree on the hill at (4, 4) when it
66⍝# stands above the water
67ˡc̲hunk ← { h →
68 top ← (1 + ˡzs + 16 × ˡxs) s̲elect r̲avel h
69 d ← top − ˡys
70 b ← (d = 1) × 3
71 b ← b + (d > 1) × (d < 5) × 2
72 b ← b + (d ≥ 5) × 1
73 b ← b + (b = 3) × (ˡys ≤ 7) × 1
74 b ← b + (b = 0) × (ˡys < 7) × 5
75 ⍝ the tree: a trunk of 3 at (4, 4), leaves around its top
76 t ← (1 + 4 + 16 × 4) s̲elect r̲avel h
77 up ← t > 7
78 ax ← a̲bs ˡxs − 4
79 az ← a̲bs ˡzs − 4
80 trunk ← up × (ax = 0) × (az = 0) × (ˡys ≥ t) × ˡys < t + 3
81 crown ← up × (ax ≤ 1) × (az ≤ 1) × (ˡys ≥ t + 2) × (ˡys ≤ t + 3) × 1 − trunk
82 b ← b + trunk × 6 − b
83 b ← b + crown × (b = 0) × 7
84 16 16 16 r̲eshape b
85}
86
87⍝# vx:c_ounts b: how many of each block, air first
88ˡc̲ounts ← { b → '+ r̲/₂ ((r̲ange 8) − 1) '= t̲able r̲avel b }
89
90⍝# x vx:s_ide b: the slice at x, as characters, up at the top
91ˡs̲ide ← { x b → r̲ev (1 + (x + 1) s̲elect b) s̲elect ˡglyphs }
92
93⍝# a column value (x by z) at every cell of its column
94ˡc̲olumn ← { m → 16 16 16 r̲eshape (1 + ˡzs + 16 × ˡxs) s̲elect r̲avel m }
95
96⍝# vx:t_op b: what is seen from above: the highest non-air block of each
97⍝# column (x by z) -- the top's height by a max-reduction down each
98⍝# column, then the block there picked by comparing heights
99ˡt̲op ← { b →
100 y1 ← 16 16 16 r̲eshape ˡys + 1
101 hi ← 'm̲ax r̲/₂ y1 × b > 0
102 '+ r̲/₂ b × y1 = ˡc̲olumn hi
103}
104
105⍝## Faces
106
107⍝# the cells' coordinates as 16 by 16 by 16 arrays
108X ← 16 16 16 r̲eshape ˡxs
109Y ← 16 16 16 r̲eshape ˡys
110Z ← 16 16 16 r̲eshape ˡzs
111
112⍝# a solid block is any but air and water
113ˡs̲olid ← { b → (b > 0) × b ≠ 5 }
114
115⍝# the exposed faces in the six directions -- west, east, down, up,
116⍝# north, south: numbered 0 to 5 -- as a 6 by 4096 Boolean array: a
117⍝# solid cell whose neighbor that way is not solid. The neighbor is a
118⍝# rotation along the axis (the six rotations of the Life idiom) with
119⍝# the plane that wrapped around made air: beyond the border is air.
120ˡe̲xposed ← { b →
121 s ← ˡs̲olid b
122 w ← s > (-1 o̲-₁ s) × X > 0
123 e ← s > (1 o̲-₁ s) × X < 15
124 d ← s > (-1 o̲-₂ s) × Y > 0
125 u ← s > (1 o̲-₂ s) × Y < 15
126 n ← s > (-1 o̲-₃ s) × Z > 0
127 so ← s > (1 o̲-₃ s) × Z < 15
128 6 4096 r̲eshape (r̲avel w) c̲at (r̲avel e) c̲at (r̲avel d) c̲at (r̲avel u) c̲at (r̲avel n) c̲at r̲avel so
129}
130
131⍝# water's surface: water with air above it, facing up
132ˡs̲urface ← { b → (b = 5) > (1 o̲-₂ b > 0) × Y < 15 }
133
134⍝# d r_ows mb: the faces of one direction as 5 rows -- x, y, z of the
135⍝# cell, the direction, the block -- from mb, the mask times 1 + the
136⍝# block (so one array carries both)
137ʰr̲ows ← { d mb →
138 k ← w̲here mb > 0
139 (5 c̲at t̲ally k) r̲eshape (k s̲elect ˡxs) c̲at (k s̲elect ˡys) c̲at (k s̲elect ˡzs) c̲at ((t̲ally k) r̲eshape d) c̲at (k s̲elect mb) − 1
140}
141
142⍝# vx:f_aces b: every face to draw, one row each -- x y z direction
143⍝# block -- the six directions' exposed faces, then water's surface
144ˡf̲aces ← { b →
145 m ← ˡe̲xposed b
146 bb ← 1 + r̲avel b
147 r ← (0 ʰr̲ows bb × 1 s̲elect m) c̲at₂ (1 ʰr̲ows bb × 2 s̲elect m) c̲at₂ (2 ʰr̲ows bb × 3 s̲elect m)
148 r ← r c̲at₂ (3 ʰr̲ows bb × 4 s̲elect m) c̲at₂ (4 ʰr̲ows bb × 5 s̲elect m) c̲at₂ (5 ʰr̲ows bb × 6 s̲elect m)
149 2 1 t̲ranspose r c̲at₂ 3 ʰr̲ows bb × r̲avel ˡs̲urface b
150}
151
152⍝# vx:c_ount f: how many faces in each direction (west east down up
153⍝# north south); a single block shows one face each way:
154⍝# >> "vx:" u_se< "Voxels"
155⍝# >> one := 16 16 16 r_eshape (vx:xs = 8) * (vx:ys = 8) * vx:zs = 8
156⍝# >> vx:c_ount vx:f_aces one
157⍝# 1 1 1 1 1 1
158ˡc̲ount ← { f → '+ r̲/₂ (r̲ange 6) '= t̲able 1 + 4 s̲elect₂ f }
159
160⍝## Drawing
161
162⍝# the corners of each direction's face, from its cell's corner, taken
163⍝# in pairs round the square (1 2, 2 3, 3 4, 4 1): x, y, z, 6 by 8 each
164ox ← 6 8 r̲eshape (8 r̲eshape 0) c̲at (8 r̲eshape 1) c̲at (0 1 1 1 1 0 0 0) c̲at (0 1 1 1 1 0 0 0) c̲at (0 1 1 1 1 0 0 0) c̲at 0 1 1 1 1 0 0 0
165oy ← 6 8 r̲eshape (0 1 1 1 1 0 0 0) c̲at (0 1 1 1 1 0 0 0) c̲at (8 r̲eshape 0) c̲at (8 r̲eshape 1) c̲at (0 0 0 1 1 1 1 0) c̲at 0 0 0 1 1 1 1 0
166oz ← 6 8 r̲eshape (0 0 0 1 1 1 1 0) c̲at (0 0 0 1 1 1 1 0) c̲at (0 0 0 1 1 1 1 0) c̲at (0 0 0 1 1 1 1 0) c̲at (8 r̲eshape 0) c̲at 8 r̲eshape 1
167
168⍝# vx:e_dges f: the faces' outlines as segments for scene: 8 points a
169⍝# face (4 edges, 2 points each), n*8 by 3, the chunk centered on the
170⍝# origin and scaled to -1..1
171ˡe̲dges ← { f →
172 d ← 1 + 4 s̲elect₂ f
173 z8 ← 8 r̲eshape 0
174 px ← (d s̲elect ox) + (1 s̲elect₂ f) '+ t̲able z8
175 py ← (d s̲elect oy) + (2 s̲elect₂ f) '+ t̲able z8
176 pz ← (d s̲elect oz) + (3 s̲elect₂ f) '+ t̲able z8
177 p ← 2 1 t̲ranspose (3 c̲at 8 × t̲ally f) r̲eshape (r̲avel px) c̲at (r̲avel py) c̲at r̲avel pz
178 ((f̲loat p) − 8.0) ÷ 8.0
179}
180
181⍝# each block's color, red green blue (air first)
182ˡcolors ← 8 3 r̲eshape 0 0 0 0.55 0.55 0.58 0.55 0.38 0.22 0.35 0.7 0.25 0.9 0.82 0.55 0.25 0.45 0.9 0.45 0.3 0.15 0.2 0.5 0.2
183
184⍝ the corners of each direction's face in order round it: the
185⍝ outlines' corners 1 3 5 7
186cx ← 1 3 5 7 s̲elect₂ ox
187cy ← 1 3 5 7 s̲elect₂ oy
188cz ← 1 3 5 7 s̲elect₂ oz
189⍝# vx:c_orners f: each face's four corners in order round it, n*4 by 3,
190⍝# in blocks -- the quads scene draws for the faces
191ˡc̲orners ← { f →
192 d ← 1 + 4 s̲elect₂ f
193 z4 ← 4 r̲eshape 0
194 px ← (d s̲elect cx) + (1 s̲elect₂ f) '+ t̲able z4
195 py ← (d s̲elect cy) + (2 s̲elect₂ f) '+ t̲able z4
196 pz ← (d s̲elect cz) + (3 s̲elect₂ f) '+ t̲able z4
197 f̲loat 2 1 t̲ranspose (3 c̲at 4 × t̲ally f) r̲eshape (r̲avel px) c̲at (r̲avel py) c̲at r̲avel pz
198}
199
200⍝# vx:q_uads f: the faces as filled quads for scene, a chunk centered
201⍝# on the origin and scaled to -1..1, like vx:e_dges
202ˡq̲uads ← { f → ((ˡc̲orners f) − 8.0) ÷ 8.0 }
203
204⍝## Worlds: many chunks
205
206⍝ A world is one array, x by 32 by z, made of 16-cubes; its exposed
207⍝ faces are found over the whole of it at once (so faces between
208⍝ chunks hide each other), then grouped by chunk for scene's ids.
209
210⍝# value noise, made by linear algebra: random heights on a grid every s
211⍝# blocks, interpolated to n by n -- M G M', M the n by k hat-function
212⍝# weights of each grid line
213ʰw̲eights ← { s n →
214 k ← 1 + n d̲iv s
215 t ← (f̲loat (r̲ange n) − 1) ÷ f̲loat s
216 0.0 m̲ax 1.0 − a̲bs t '− t̲able f̲loat (r̲ange k) − 1
217}
218ʰn̲oise ← { s n →
219 m ← s ʰw̲eights n
220 k ← 1 + n d̲iv s
221 g ← (f̲loat r̲oll! (k × k) r̲eshape 1000) ÷ 1000.0
222 m '+ '× i̲nner ((k c̲at k) r̲eshape g) '+ '× i̲nner 2 1 t̲ranspose m
223}
224
225⍝# vx:h_eights n: an n by n height field (x by z), three octaves of
226⍝# value noise -- every 16, 8 and 4 blocks -- from 4 to 29 (seeded)
227ˡh̲eights ← { n →
228 v ← (16.0 × 16 ʰn̲oise n) + (7.0 × 8 ʰn̲oise n) + 3.0 × 4 ʰn̲oise n
229 4 m̲ax 29 m̲in f̲loor 4.0 + v
230}
231
232⍝# a world's cells' coordinates, for a shape nx ny nz (x slowest)
233ʰc̲oords ← { sh →
234 j ← (r̲ange '× r̲/ sh) − 1
235 yz ← (2 s̲elect sh) × 3 s̲elect sh
236 (3 c̲at t̲ally j) r̲eshape (j d̲iv yz) c̲at ((j d̲iv 3 s̲elect sh) m̲od 2 s̲elect sh) c̲at j m̲od 3 s̲elect sh
237}
238
239⍝# vx:t_errain h: the world on a height field h (nx by nz), 32 tall:
240⍝# grass, dirt, stone, water filling air below 14, sand at the shore --
241⍝# the chunk's rules, over the whole world
242ˡt̲errain ← { h →
243 nx ← 1 s̲elect s̲hape h
244 nz ← 2 s̲elect s̲hape h
245 c ← ʰc̲oords nx c̲at 32 c̲at nz
246 xs ← 1 s̲elect c
247 ys ← 2 s̲elect c
248 zs ← 3 s̲elect c
249 d ← ((1 + zs + nz × xs) s̲elect r̲avel h) − ys
250 b ← (d = 1) × 3
251 b ← b + (d > 1) × (d < 5) × 2
252 b ← b + (d ≥ 5) × 1
253 b ← b + (b = 3) × (ys ≤ 14) × 1
254 b ← b + (b = 0) × (ys < 14) × 5
255 (nx c̲at 32 c̲at nz) r̲eshape b
256}
257
258⍝# t vx:t_ree b: a tree at column t (x z) when it stands on grass: a
259⍝# trunk of 4 and a crown of leaves, placed into b -- only the tree's
260⍝# own cells are worked out (their indexes into b), then set by a
261⍝# membership mask, so a tree costs little in a big block
262ˡt̲ree ← { t b →
263 sh ← s̲hape b
264 ny ← 2 s̲elect sh
265 nz ← 3 s̲elect sh
266 tx ← 1 s̲elect t
267 tz ← 2 s̲elect t
268 v ← r̲avel b
269 col ← (1 + tz + nz × ((r̲ange ny) − 1) + ny × tx) s̲elect v
270 0 = '+ r̲/ col = 3 ? b
271 y0 ← 1 + '+ r̲/ (col = 3) × (r̲ange ny) − 1
272 ty ← y0 + (r̲ange 4) − 1
273 ty ← (ty < ny) r̲eplicate ty
274 trunk ← 1 + tz + nz × ty + ny × tx
275 d5 ← (r̲ange 5) − 3
276 dx ← r̲avel d5 '{ ⍺ + 0 × ⍵ } t̲able d5
277 dz ← r̲avel d5 '{ ⍵ + 0 × ⍺ } t̲able d5
278 wide ← ((a̲bs dx) + a̲bs dz) < 4
279 small ← ((a̲bs dx) ≤ 1) × (a̲bs dz) ≤ 1
280 u̲p ← { y m →
281 y ≥ ny ? 0 r̲eshape 0
282 1 + (tz + m r̲eplicate dz) + nz × y + ny × tx + m r̲eplicate dx
283 }
284 crown ← ((y0 + 3) u̲p wide) c̲at ((y0 + 4) u̲p wide) c̲at (y0 + 5) u̲p small
285 n ← t̲ally v
286 v ← v + ((r̲ange n) m̲ember? trunk) × 6 − v
287 v ← v + ((r̲ange n) m̲ember? crown) × (v = 0) × 7
288 sh r̲eshape v
289}
290
291⍝# vx:w_orldFaces b: every face of a world, one row each -- x y z
292⍝# direction block -- as vx:f_aces does for a chunk, the borders of the
293⍝# world air
294ˡw̲orldFaces ← { b →
295 sh ← s̲hape b
296 c ← ʰc̲oords sh
297 s ← ˡs̲olid b
298 xs ← sh r̲eshape 1 s̲elect c
299 ys ← sh r̲eshape 2 s̲elect c
300 zs ← sh r̲eshape 3 s̲elect c
301 mx ← (1 s̲elect sh) − 1
302 my ← (2 s̲elect sh) − 1
303 mz ← (3 s̲elect sh) − 1
304 w ← s > (-1 o̲-₁ s) × xs > 0
305 e ← s > (1 o̲-₁ s) × xs < mx
306 d ← s > (-1 o̲-₂ s) × ys > 0
307 u ← s > (1 o̲-₂ s) × ys < my
308 n ← s > (-1 o̲-₃ s) × zs > 0
309 so ← s > (1 o̲-₃ s) × zs < mz
310 top ← (b = 5) > (1 o̲-₂ b > 0) × ys < my
311 bb ← 1 + r̲avel b
312 r̲w ← { d m →
313 k ← w̲here m > 0
314 (5 c̲at t̲ally k) r̲eshape (k s̲elect 1 s̲elect c) c̲at (k s̲elect 2 s̲elect c) c̲at (k s̲elect 3 s̲elect c) c̲at ((t̲ally k) r̲eshape d) c̲at (k s̲elect m) − 1
315 }
316 r ← (0 r̲w bb × r̲avel w) c̲at₂ (1 r̲w bb × r̲avel e) c̲at₂ (2 r̲w bb × r̲avel d) c̲at₂ (3 r̲w bb × r̲avel u)
317 r ← r c̲at₂ (4 r̲w bb × r̲avel n) c̲at₂ (5 r̲w bb × r̲avel so) c̲at₂ 3 r̲w bb × r̲avel top
318 2 1 t̲ranspose r
319}
320
321⍝# vx:c_hunkOf f: the chunk of each face (1 up): x, z and y in 16s
322ˡc̲hunkOf ← { f → 1 + ((1 s̲elect₂ f) d̲iv 16) + (4 × (3 s̲elect₂ f) d̲iv 16) + 16 × (2 s̲elect₂ f) d̲iv 16 }
323
324⍝# ts vx:f_orest b: trees at the columns ts (n by 2: x z), each where it
325⍝# stands on grass -- vx:t_ree folded over them
326ˡf̲orest ← { ts b →
327 boxes ← ('{ ⍵ s̲elect ts } m̲ap r̲ange t̲ally ts) c̲at e̲nclose b
328 d̲isclose '{ e̲nclose (d̲isclose ⍺) ˡt̲ree d̲isclose ⍵ } r̲/ boxes
329}
330
331⍝## Endless worlds
332
333⍝# a grid point's random value, 0 to 1, from its coordinates alone (i
334⍝# by j, any integers): the same point always gets the same value, so
335⍝# any part of an endless world can be made by itself and fits its
336⍝# neighbors
337⍝# >> "vx:" u_se< "Voxels"
338⍝# >> (3 vx:h_ash 4) = 3 vx:h_ash 4
339⍝# 1
340ˡh̲ash ← { i j →
341 v ← 43758.5453 × s̲in (12.9898 × f̲loat i) '+ t̲able 78.233 × f̲loat j
342 v − f̲loat f̲loor v
343}
344
345⍝ the smooth weight of grid line k for the coordinates t (in grid
346⍝ units): smoothstep of 1 - |t - k|, 0 beyond a grid step
347ʰw̲eight ← { t k →
348 d ← 0.0 m̲ax 1.0 − a̲bs t '− t̲able f̲loat k
349 d × d × 3.0 − 2.0 × d
350}
351
352⍝ s n_oiseOf c: value noise every s blocks over the n by n blocks from
353⍝ c (x0 z0): grid values hashed from their coordinates, interpolated as
354⍝ M G M'
355ʰn̲oiseOf ← { s c →
356 x0 ← 1 s̲elect c
357 z0 ← 2 s̲elect c
358 n ← 3 s̲elect c
359 tx ← (f̲loat x0 + (r̲ange n) − 1) ÷ f̲loat s
360 tz ← (f̲loat z0 + (r̲ange n) − 1) ÷ f̲loat s
361 gx ← (f̲loor 'm̲in r̲/ tx) + (r̲ange 2 + (f̲loor 'm̲ax r̲/ tx) − f̲loor 'm̲in r̲/ tx) − 1
362 gz ← (f̲loor 'm̲in r̲/ tz) + (r̲ange 2 + (f̲loor 'm̲ax r̲/ tz) − f̲loor 'm̲in r̲/ tz) − 1
363 (tx ʰw̲eight gx) '+ '× i̲nner (gx ˡh̲ash gz) '+ '× i̲nner 2 1 t̲ranspose tz ʰw̲eight gz
364}
365
366⍝# vx:h_eightsAt x0 z0 n: the heights of the n by n columns from block
367⍝# (x0, z0), x by z, of the endless world: three octaves of value noise
368⍝# (every 32, 16 and 8 blocks), 3 to 29, the sea at 14 -- any square
369⍝# anywhere, always the same
370ˡh̲eightsAt ← { c →
371 v ← (18.0 × 32 ʰn̲oiseOf c) + (8.0 × 16 ʰn̲oiseOf c) + 3.0 × 8 ʰn̲oiseOf c
372 3 m̲ax 29 m̲in f̲loor 2.0 + v
373}
374
375⍝ the cells of a 16 by 32 by 16 column inside its 18 by 32 by 18 block
376⍝ (a border of one from the neighbors), as indexes into the bigger one
377cell ← (r̲ange 8192) − 1
378inner ← 1 + (1 + cell m̲od 16) + 18 × ((cell d̲iv 16) m̲od 32) + 32 × 1 + cell d̲iv 512
379
380⍝# vx:p_atch c: column c (cx cz) of the endless world, 16 by 32 by 16
381⍝# blocks: made with a border of one block from its neighbors' heights,
382⍝# so its faces at the border hide where a neighbor is solid; trees (two
383⍝# places hashed from the column, kept inside it). A box of its faces
384⍝# (world coordinates, one row each: x y z direction block) and a box of
385⍝# its solid mask (16 by 32 by 16, flat, x slowest)
386ˡp̲atch ← { c →
387 x0 ← (16 × 1 s̲elect c) − 1
388 z0 ← (16 × 2 s̲elect c) − 1
389 h ← ˡh̲eightsAt x0 c̲at z0 c̲at 18
390 b ← ˡt̲errain h
391 r ← (1 s̲elect c) ˡh̲ash 2 s̲elect c
392 q ← (2 s̲elect c) ˡh̲ash 1 s̲elect c
393 t ← 4 + f̲loor 10.0 × (r̲avel r) c̲at (r̲avel q) c̲at (r̲avel r × q) c̲at r̲avel 1.0 − r × q
394 b ← (2 2 r̲eshape t) ˡf̲orest b
395 f ← ˡw̲orldFaces b
396 keep ← ((1 s̲elect₂ f) ≥ 1) × ((1 s̲elect₂ f) ≤ 16) × ((3 s̲elect₂ f) ≥ 1) × (3 s̲elect₂ f) ≤ 16
397 f ← keep r̲eplicate f
398 f ← f + ((t̲ally f) c̲at 5) r̲eshape x0 c̲at 0 c̲at z0 c̲at 0 0
399 (e̲nclose f) c̲at e̲nclose inner s̲elect r̲avel ˡs̲olid b
400}
401
402⍝## Columns, quickly
403
404⍝ the 18 by 32 by 18 block of a column with its border: its cells'
405⍝ coordinates, made once (flat, x slowest, and as arrays), and which
406⍝ cells are the column's own (x and z from 1 to 16)
407cc ← ʰc̲oords 18 32 18
408cx18 ← 1 s̲elect cc
409cy18 ← 2 s̲elect cc
410cz18 ← 3 s̲elect cc
411X18 ← 18 32 18 r̲eshape cx18
412Y18 ← 18 32 18 r̲eshape cy18
413Z18 ← 18 32 18 r̲eshape cz18
414own ← (cx18 ≥ 1) × (cx18 ≤ 16) × (cz18 ≥ 1) × cz18 ≤ 16
415
416⍝# vx:c_olumnBlocks c: the blocks of column c (cx cz) of the endless
417⍝# world with a border of one from its neighbors, 18 by 32 by 18: the
418⍝# heights, the terrain's rules, two trees placed by hash -- the first
419⍝# of the three parts of making a column (about 12 ms)
420ˡc̲olumnBlocks ← { c →
421 x0 ← (16 × 1 s̲elect c) − 1
422 z0 ← (16 × 2 s̲elect c) − 1
423 h ← ˡh̲eightsAt x0 c̲at z0 c̲at 18
424 d ← ((1 + cz18 + 18 × cx18) s̲elect r̲avel h) − cy18
425 b ← (d = 1) × 3
426 b ← b + (d > 1) × (d < 5) × 2
427 b ← b + (d ≥ 5) × 1
428 b ← b + (b = 3) × (cy18 ≤ 14) × 1
429 b ← b + (b = 0) × (cy18 < 14) × 5
430 b ← 18 32 18 r̲eshape b
431 r ← (1 s̲elect c) ˡh̲ash 2 s̲elect c
432 q ← (2 s̲elect c) ˡh̲ash 1 s̲elect c
433 t ← 4 + f̲loor 10.0 × (r̲avel r) c̲at (r̲avel q) c̲at (r̲avel r × q) c̲at r̲avel 1.0 − r × q
434 (2 2 r̲eshape t) ˡf̲orest b
435}
436
437⍝# vx:c_olumnMask b: the solid mask of a column's own cells (16 by 32
438⍝# by 16, flat, x slowest), from its blocks
439ˡc̲olumnMask ← { b → inner s̲elect r̲avel ˡs̲olid b }
440
441⍝# c vx:c_olumnFaces b: the faces of column c's own cells, in world
442⍝# coordinates, one row each (x y z direction block) -- found over the
443⍝# block with its border, so faces against a solid neighbor hide; the
444⍝# second part of making a column
445ˡc̲olumnFaces ← { c b →
446 s ← ˡs̲olid b
447 w ← s > (-1 o̲-₁ s) × X18 > 0
448 e ← s > (1 o̲-₁ s) × X18 < 17
449 d ← s > (-1 o̲-₂ s) × Y18 > 0
450 u ← s > (1 o̲-₂ s) × Y18 < 31
451 n ← s > (-1 o̲-₃ s) × Z18 > 0
452 so ← s > (1 o̲-₃ s) × Z18 < 17
453 top ← (b = 5) > (1 o̲-₂ b > 0) × Y18 < 31
454 bb ← own × 1 + r̲avel b
455 x0 ← (16 × 1 s̲elect c) − 1
456 z0 ← (16 × 2 s̲elect c) − 1
457 r̲w ← { d m →
458 k ← w̲here m > 0
459 (5 c̲at t̲ally k) r̲eshape (x0 + k s̲elect cx18) c̲at (k s̲elect cy18) c̲at (z0 + k s̲elect cz18) c̲at ((t̲ally k) r̲eshape d) c̲at (k s̲elect m) − 1
460 }
461 r ← (0 r̲w bb × r̲avel w) c̲at₂ (1 r̲w bb × r̲avel e) c̲at₂ (2 r̲w bb × r̲avel d) c̲at₂ (3 r̲w bb × r̲avel u)
462 r ← r c̲at₂ (4 r̲w bb × r̲avel n) c̲at₂ (5 r̲w bb × r̲avel so) c̲at₂ 3 r̲w bb × r̲avel top
463 2 1 t̲ranspose r
464}