luv

Workshop wiki

blocks.lisp

luvcraft/blocks.lisp

system luvcraft/core · 139 definitions · on GitHub

The semantic block vocabulary and its procedural texture atlas.

Blocks and faces are ordinary CLOS objects so the interesting semantic choices stay inspectable and redefinable at the REPL. The material palette here is what the player places, what the mesher shades, and what the shader lab browses; the atlas is generated arithmetic, not an asset.

in-package#:luvcraft
defclassblock-kind
name:initarg:name:readerblock-kind-name
face-tiles:initarg:face-tiles:readerblock-kind-face-tiles
categories:initarg:categories:initformnil:readerblock-kind-categories
display-color:initarg:display-color:initform'
0.50.50.5
:readerblock-kind-display-color
placeable-p:initarg:placeable-p:initformt:readerblock-kind-placeable-p

Light behavior is distinct from collision: opacity is how much a cell costs propagating light, emission seeds the propagated blocklight field, and surface emission is the material's own visible radiance. One glowing crystal may configure both emissions, but they are different facts.

light-opacity:initarg:light-opacity:initform15:type
integer015
:quantity
:quantity:block-light-attenuation-step:unit:one
:readerblock-kind-light-opacity
light-emission:initarg:light-emission:initform0:type
integer015
:quantity
:quantity:block-light-emission-step:unit:one
:readerblock-kind-light-emission
surface-emission:initarg:surface-emission:initform0.0:typereal:quantity
:quantity:material-emission:unit:one
:readerblock-kind-surface-emission
defmethodshared-initialize:after
slot-names&key
declare
ignoreslot-names

A class prototype -- which CLIM's presentation dispatch asks for, and which a class redefinition updates through here -- has no slots at all and is not a block kind anyone defined; leave it alone.

unless
slot-boundpblock'name
unless
keywordp
block-kind-nameblock
error"A block kind name must be a keyword, not ~S."
block-kind-nameblock
let
tiles
block-kind-face-tilesblock
unless
and
listptiles
evenp
lengthtiles
error"Block kind ~S has invalid face tiles ~S."
block-kind-nameblock
tiles
loopfor
facetile
ontilesby#'cddrunless
and
keywordpface
keywordptile
do
error"Block kind ~S has non-keyword face tile ~S => ~S."
block-kind-nameblock
facetile
unless
every#'keywordp
block-kind-categoriesblock
error"Block kind ~S has invalid categories ~S."
block-kind-nameblock
block-kind-categoriesblock
unless
and
=3
length
block-kind-display-colorblock
every
lambda
component
and
realpcomponent
<=0component1
block-kind-display-colorblock
error"Block kind ~S has invalid display color ~S."
block-kind-nameblock
block-kind-display-colorblock
defgenericblock-solid-p
block
defgenericblock-face-tile
blockface
defgenericblock-light-opacity
block
:documentation

How strongly block attenuates propagated light, 0..15.

defgenericblock-light-emission
block
:documentation

The blocklight level block seeds into its own cell, 0..15.

defgenericblock-surface-emission
block
:documentation

block's own linear material radiance, independent of propagated light.

defmethodblock-solid-p
blocknull
nil
defmethodblock-light-opacity
blocknull
0
defmethodblock-light-emission
blocknull
0
defmethodblock-surface-emission
blocknull
0.0
defmethodblock-light-opacity
block-kind-light-opacityblock
defmethodblock-light-emission
block-kind-light-emissionblock
defmethodblock-surface-emission
block-kind-surface-emissionblock
defclassblock-face
name:initarg:name:readerblock-face-name
neighbor:initarg:neighbor:readerblock-face-neighbor
corners:initarg:corners:readerblock-face-corners
defunmake-block-face
nameneighborcorners
make-instance'block-face:namename:neighborneighbor:cornerscorners
defunblock-face-local-uv
facecorner

Project corner onto face's plane as tile-local UV coordinates.

The rule is read from the face's own outward normal rather than its name: horizontal faces map world X,Z straight across the tile, and lateral faces keep the world-horizontal axis as U while flipping world Y into V so tiles hang upright.

let
normal
block-face-neighborface
cond
not
zerop
voxel-direction-dynormal
values
firstcorner
thirdcorner
not
zerop
voxel-direction-dznormal
values
firstcorner
-1
secondcorner
t
values
thirdcorner
-1
secondcorner
defmethodblock-face-tile
let
tiles
block-kind-face-tilesblock
or
getftiles
block-face-nameface
and
member
block-face-nameface
'
:left:right:back:front
getftiles:side
getftiles:all
error"No texture tile for ~S face ~S."
block-kind-nameblock
block-face-nameface
defvar*block-kinds*nil
defclasstape-block-kind
:documentation

The film reel a player loads with a YouTube code; see luvcraft/tape.lisp.

A class of its own rather than a name test, so activating one is a method on the kind and no other block's activation has to know about tapes.

defclassspring-block-kind
:documentation

A block that throws things: a fountain of water, a well of lava. What it throws is decided by its name in luvcraft/balls.lisp; the class is what lets placing and removing one be a method rather than a name test.

defunensure-block-kind
currentname&keyface-tilescategories
display-color'
0.50.50.5
placeable-pt
light-opacity15
light-emission0
surface-emission0.0

Define name while preserving current's identity across live redefinition.

class is the block kind class to make; a current of another class is replaced rather than reinitialized, since its methods would be the wrong ones.

let
initargs
list:namename:face-tilesface-tiles:categoriescategories:display-colordisplay-color:placeable-pplaceable-p:light-opacitylight-opacity:light-emissionlight-emission:surface-emissionsurface-emission
if
and
typepcurrent'block-kind
eq
class-name
class-ofcurrent
class
eqname
block-kind-namecurrent
apply#'reinitialize-instancecurrentinitargs
apply#'make-instanceclassinitargs
defmacrodefine-block-kinds
&bodydefinitions

Define the complete ordered block vocabulary.

Each definition is (variable NAME &rest BLOCK-KIND-INITARGS), optionally followed by a variable documentation string. Re-evaluation updates existing objects in place, so resident worlds and live inventories observe the new definition.

let
variables
mapcar#'firstdefinitions
`
progn,@
loopfor
variablename.options
indefinitionsfordocumentation=
and
stringp
firstoptions
popoptions
collect`
progn
setf*block-kinds*
list,@variables
define-block-kinds
*grass-block*:grass:face-tiles'
:top:grass-top:side:grass-side:bottom:dirt
:categories'
:natural
:display-color'
0.280.660.25
*dirt-block*:dirt:face-tiles'
:all:dirt
:categories'
:natural
:display-color'
0.480.310.18
*stone-block*:stone:face-tiles'
:all:stone
:categories'
:building
:display-color'
0.490.520.54
*wood-block*:wood:face-tiles'
:top:wood-end:bottom:wood-end:side:wood-side
:categories'
:building
:display-color'
0.570.360.17
*leaf-block*:leaves:face-tiles'
:all:leaves
:categories'
:natural
:display-color'
0.190.500.22
*sand-block*:sand:face-tiles'
:all:sand
:categories'
:natural
:display-color'
0.780.680.37
*snow-block*:snow:face-tiles'
:top:snow:side:snow:bottom:dirt
:categories'
:natural
:display-color'
0.860.910.94
*crystal-block*:crystal:face-tiles'
:all:crystal
:categories'
:luminous
:display-color'
0.180.860.88
:light-emission12:surface-emission1.2
*terminal-block*:terminal"The graphite display-block material used by world-native terminals.":face-tiles'
:all:terminal
:categories'
:building:luminous
:display-color'
0.130.310.34
:surface-emission0.16
*urbit-block*:urbit

The Martian computer: a white planet sigil on a near-black field, the tenth quickbar material, reached by the 0 key at the end of the number row.

:face-tiles'
:all:urbit
:categories'
:building:luminous
:display-color'
0.070.070.09
:surface-emission0.22
*gravel-block*:gravel:face-tiles'
:all:gravel
:categories'
:natural
:display-color'
0.460.440.40
*clay-block*:clay:face-tiles'
:all:clay
:categories'
:natural
:display-color'
0.630.680.70
*mud-block*:mud:face-tiles'
:all:mud
:categories'
:natural
:display-color'
0.310.200.12
*moss-block*:moss:face-tiles'
:all:moss
:categories'
:natural
:display-color'
0.290.450.16
*cactus-block*:cactus:face-tiles'
:top:cactus-end:bottom:cactus-end:side:cactus-side
:categories'
:natural
:display-color'
0.200.490.24
*cobblestone-block*:cobblestone:face-tiles'
:all:cobblestone
:categories'
:building
:display-color'
0.420.430.41
*stone-bricks-block*:stone-bricks:face-tiles'
:all:stone-bricks
:categories'
:building
:display-color'
0.530.540.51
*bricks-block*:bricks:face-tiles'
:all:bricks
:categories'
:building
:display-color'
0.630.280.19
*planks-block*:planks:face-tiles'
:all:planks
:categories'
:building
:display-color'
0.660.450.23
*sandstone-block*:sandstone:face-tiles'
:all:sandstone
:categories'
:building
:display-color'
0.790.680.43
*slate-block*:slate:face-tiles'
:all:slate
:categories'
:building
:display-color'
0.250.290.32
*tape-block*:tape

A blank film reel. Focus it and it asks for a YouTube code; when the download lands it has become a film, which is a block that can be picked up and carried. See luvcraft/tape.lisp.

:class'tape-block-kind:face-tiles'
:front:tape-flange:back:tape-flange:top:reel-rim:bottom:reel-rim:left:reel-rim:right:reel-rim
:categories'
:building
:display-color'
0.360.340.32
*orb-mote-block*:orb-mote"The bright grain a progress orb is made of; never placed, only emitted.":face-tiles'
:all:crystal
:categories'
:luminous
:display-color'
0.90.951.0
:placeable-pnil:light-emission0:surface-emission5.0
*fountain-block*:fountain

A stone basin that throws water into the air, drop by drop; see luvcraft/balls.lisp for what the drops do.

:class'spring-block-kind:face-tiles'
:top:water:side:cobblestone:bottom:cobblestone
:categories'
:building
:display-color'
0.350.550.75
*lava-spring-block*:lava-spring

A slate well of lava that spits glowing gobbets which cool where they land; see luvcraft/balls.lisp.

:class'spring-block-kind:face-tiles'
:top:lava:side:slate:bottom:slate
:categories'
:building:luminous
:display-color'
0.950.450.10
:light-emission11:surface-emission0.0
*flowers-block*:flowers

Meadow grass in bloom: a grass block whose top carries small bright flowers. The birthday meadow freckles its lawns with these.

:face-tiles'
:top:flowers-top:side:grass-side:bottom:dirt
:categories'
:natural
:display-color'
0.440.620.31
eval-when
:load-toplevel:execute

ensure-block-kind preserves identities across live redefinition, so deleting a source definition alone would leave an old image offering the retired material. Agents no longer inhabit this vocabulary.

setf*block-kinds*
delete:gnome*block-kinds*:key#'block-kind-name:test#'eq
defunplaceable-block-kinds

Return the numbered material palette used by luvcraft and its tools.

remove-if-not#'block-kind-placeable-p*block-kinds*
defunblock-kind-named
name&optional
error-pt

Return the shared block kind whose durable semantic name is name.

When error-p is true, signal an error rather than returning NIL for an unknown name. Save files and other external descriptions refer to block kinds through this vocabulary instead of printing CLOS object identities.

or
findname*block-kinds*:key#'block-kind-name:test#'eq
whenerror-p
error"No block kind is named ~S."name

Painted tiles fill a prefix of a renderer-owned atlas. Capacity is a live policy rather than mesh meaning: refresh-block-atlas replaces textures when this changes, while vertices retain their mapping-scoped tile offsets.

defparameter*block-atlas-tile-capacity*64"How many tiles wide a newly materialized block atlas texture is."
defparameter*block-atlas-tile-domain*
domains:make-keyword-vocabulary-domain'
:grass-top:grass-side:dirt:stone:wood-side:wood-end:leaves:sand:snow:crystal:terminal:gravel:clay:mud:moss:cactus-side:cactus-end:cobblestone:stone-bricks:bricks:planks:sandstone:slate:turtle-carapace:turtle-skin:turtle-plastron:player-skin:player-sleeve:phone-body:phone-screen:tape-flange:reel-rim:film-flange:ball:water:lava:urbit:flowers-top

The replaceable interpretation of atlas tile identities as dense offsets.

Re-evaluating this definition constructs a new domain. Existing offsets stay closed by the old domain; atlas refresh and later publication explicitly adopt the new one instead of pretending a vocabulary is materialized only once.

defunblock-atlas-tile-offset
tile&optional

Return tile's dense offset under the explicitly supplied atlas domain.

defunblock-atlas-tile-at-offset
offset&optional

Return the semantic tile identity at offset under atlas domain.

defconstant+block-atlas-texture-format+:rgba8-unorm-srgb
defgenericpaint-block-atlas-relief
tilexy
:documentation

Return the 0..255 surface height of atlas tile tile at tile-local X,Y.

Like the colour, each named tile is one EQL method, so a live image can re-sculpt a single material's micro-surface and rebuild both atlases without touching the rest of the palette.

See #CHUKWD for why relief and normals are generated beside colour rather than arriving as authored assets.

defunblock-atlas-byte
value
max0
min255
roundvalue
defunpack-block-atlas-rgba
redgreenblue
logior#xff000000
defunblock-atlas-variation
xytile

Fine colour grain modulated by tile's shared procedural relief.

defunshaded-block-atlas-pixel
redgreenblue&optional
variation0
pack-block-atlas-rgba
+redvariation
+greenvariation
+bluevariation
defunblock-atlas-brick-mortar-p
xybrick-widthcourse-height

Whether X,Y lies in staggered mortar for a regular masonry bond.

let*
course
floorycourse-height
offset
if
oddpcourse
floorbrick-width2
0
or
zerop
modycourse-height
zerop
mod
+xoffset
brick-width
defunblock-atlas-plate-distance
xywidthheight&key
stagger-pt

Return 0..1 distance from X,Y to the centre of its width by height plate.

The same bond block-atlas-brick-mortar-p reads as a mask, read as a shape instead: zero in the middle of a panel and one along its boundary, so a plated surface can be both coloured and domed from one expression.

let*
offset
if
andstagger-p
oddpcourse
0
u
mod
+xoffset
width
half-u
/2.0
half-v
/2.0
max
/
abs
-uhalf-u
half-u
/
abs
-vhalf-v
half-v
defgenericpaint-block-atlas-tile
tilexy
:documentation

Return the packed rgba pixel of atlas tile tile at tile-local X,Y.

Each named tile is one EQL method, so a live image can repaint a single material and rebuild the atlas without touching the rest of the palette.

defmethodpaint-block-atlas-tile
tilexy
declare
ignorexy
error"Unknown block atlas tile ~S."tile
defmethodpaint-block-atlas-tile
tile
eql:grass-top
xy

Grass top.

defmethodpaint-block-atlas-tile
tile
eql:grass-side
xy

Grass side: a green fringe over dirt.

let
variation
if
<y4
shaded-block-atlas-pixel9113363variation
shaded-block-atlas-pixel1168254
roundvariation2
defmethodpaint-block-atlas-tile
tile
eql:stone
xy

Stone, with sparse bright flecks.

shaded-block-atlas-pixel116121125
+
if
zerop
mod
+
*x3
*y5
19
200
defmethodpaint-block-atlas-tile
tile
eql:wood-side
xy

Wood bark, with vertical grain stripes.

defmethodpaint-block-atlas-tile
tile
eql:wood-end
xy

Wood end grain: concentric rings around the tile centre.

let*
dx
-x7.5
dy
-y7.5
ring
mod
floor
+
*dxdx
*dydy
18
defmethodpaint-block-atlas-tile
tile
eql:leaves
xy

Leaves: a strong checker so the canopy reads as foliage.

defmethodpaint-block-atlas-tile
tile
eql:sand
xy

Sand, with sparse darker grains.

shaded-block-atlas-pixel172157122
+
if
zerop
mod
+x
*y3
13
130
defmethodpaint-block-atlas-tile
tile
eql:snow
xy

Snow, with sparse glints.

shaded-block-atlas-pixel219231236
+
if
zerop
mod
+
*x5
*y7
23
140
defmethodpaint-block-atlas-tile
tile
eql:crystal
xy

Blue crystal, with bright diagonal facets.

let*
diagonal
facet
if
or
<=diagonal1
<=
abs
-
+xy
15
1
420
variation
pack-block-atlas-rgba
+72
roundvariation3
edge
+176
roundvariation2
facetedge
+235variationfacetedge
defmethodpaint-block-atlas-tile
tile
eql:terminal
xy

Terminal graphite: a quiet face with a raised per-block bezel.

let*
variation
bezel
+outer-edgeinner-edge
pack-block-atlas-rgba
+18variationbezel
+25variationbezel
+36variationbezel
defmethodpaint-block-atlas-tile
tile
eql:gravel
xy

Gravel: mixed cool and warm stones.

let*
variation
+
-
modgrain43
21
shaded-block-atlas-pixel11110799variation
defmethodpaint-block-atlas-tile
tile
eql:clay
xy

Clay: cool compact earth with faint horizontal bands.

shaded-block-atlas-pixel146158163
+
case
mody6
0-7
1-3
t2
defmethodpaint-block-atlas-tile
tile
eql:mud
xy

Mud: dark wet clods with occasional glossy pockets.

defmethodpaint-block-atlas-tile
tile
eql:moss
xy

Moss: dense green cushions mottled across the face.

let
clump
pack-block-atlas-rgba
+67
roundclump8
+115
roundclump4
+35
roundclump10
defmethodpaint-block-atlas-tile
tile
eql:cactus-side
xy

Cactus side: vertical ribs dotted with pale spines.

let*
rib
case
modx5
0-18
18
218
38
t-10
spine
if
zerop
mod
+
*x3
*y5
17
340
pack-block-atlas-rgba
+42ribspine
+125ribspine
+55
roundrib2
spine
defmethodpaint-block-atlas-tile
tile
eql:cactus-end
xy

Cactus top: a radial cut surface around a dark green rind.

let*
dx
-x7.5
dy
-y7.5
radius
sqrt
+
*dxdx
*dydy
rind
if
>radius5.5
-350
ring
round
*7
sin
*radius2.3
pack-block-atlas-rgba
+83rindring
+151rindring
+68rind
roundring2
defmethodpaint-block-atlas-tile
tile
eql:cobblestone
xy

Cobblestone: irregular grey stones divided by dark joints.

let*
joint
or
zerop
mod
+x
*2y
7
zerop
mod
+
*3x
y
13
variation
ifjoint
shaded-block-atlas-pixel123126120variation
defmethodpaint-block-atlas-tile
tile
eql:stone-bricks
xy

Stone bricks in a pale staggered bond.

defmethodpaint-block-atlas-tile
tile
eql:bricks
xy

Fired red bricks with warm variation and deep mortar.

defmethodpaint-block-atlas-tile
tile
eql:planks
xy

Sawn planks with horizontal seams and wandering grain.

let
seam
zerop
mody5
grain
round
*9
sin
/
+
*x2
y
2.4
defmethodpaint-block-atlas-tile
tile
eql:sandstone
xy

Cut sandstone with broad sediment bands.

let
band
case
mody7
0-18
1-8
57
t0
defmethodpaint-block-atlas-tile
tile
eql:slate
xy

Slate: dark blue-grey layers with fine pale cleavage lines.

let
seam
or
zerop
mody5
and
zerop
mody3
>
mod
+xy
7
4

Not every atlas tile is a material the player places. The last three belong to the animals which walk over the terrain rather than to the terrain itself: a critter model is built from small textured boxes drawn by the ordinary block surface pipeline, so its hide is painted by exactly the same per-tile arithmetic as stone or moss. See CRITTERS.LISP.

defconstant+turtle-carapace-tile+:turtle-carapace
defconstant+turtle-skin-tile+:turtle-skin
defconstant+turtle-plastron-tile+:turtle-plastron

A critter tile is stretched across a box face a fraction of a cell wide rather than tiled over a whole block, so its pattern is deliberately several times finer than a terrain material's: roughly three scutes across a shell rather than two plates across a wall.

defmethodpaint-block-atlas-tile
tile
eql:turtle-carapace
xy

Turtle carapace: small staggered scutes with dark keratin joints.

defmethodpaint-block-atlas-tile
tile
eql:turtle-skin
xy

Turtle skin: dark olive hide pebbled with paler flecks.

let
pebble
fleck
pack-block-atlas-rgba
+98
roundpebble5
fleck
+116
roundpebble4
fleck
+56
roundpebble7
roundfleck2
defunturtle-plastron-seam-p
xy

Whether X,Y lies in the straight seam between two belly plates.

or
zerop
modx6
zerop
mody5
defmethodpaint-block-atlas-tile
tile
eql:turtle-plastron
xy

Turtle plastron: pale horn plates in a straight, unstaggered bond.

let
variation

Colour is only half of what a material looks like. The other half is its micro-surface: whether it is granular, grooved, tufted, or faceted. The normal atlas carries that as a height field and the unit normal derived from it, painted by the same per-tile arithmetic that paints the colour. The block shader reads that normal directly to perturb its shading normal.

defunblock-atlas-lattice-hash
xysalt

A small deterministic hash of one integer lattice site into 0..255.

let
value
+
*x374761393
*y668265263
*salt2654435761
setfvalue
logand
logxorvalue
ashvalue-13
#xffffffff
setfvalue
logand
*value1274126177
#xffffffff
ldb
byte813
value
defunblock-atlas-clump
xysaltperiod

Smooth 0..255 clumping at period, so a material can read as tufted.

let*
cx
floorxperiod
cy
flooryperiod
fx
/
modxperiod
floatperiod
fy
/
modyperiod
floatperiod
sx
*fxfx
-3.0
*2.0fx
sy
*fyfy
-3.0
*2.0fy
round
+
*
+a
*
-ba
sx
-1.0sy
*
+c
*
-dc
sx
sy
defmethodpaint-block-atlas-relief
tilexy

A plausible default: fine grain, so a new material is never dead flat.

defmethodpaint-block-atlas-relief
tile
eql:grass-top
xy

Grass top: blades clumped into tufts.

defmethodpaint-block-atlas-relief
tile
eql:grass-side
xy

Grass side: a ragged fringe over dirt clods.

defmethodpaint-block-atlas-relief
tile
eql:dirt
xy

Dirt: rounded clods with grit between them.

defmethodpaint-block-atlas-relief
tile
eql:stone
xy

Stone: granular, cut by a couple of shallow cracks.

let
crack
if
or
zerop
mod
+
*x3
y
11
zerop
mod
+x
*y5
13
-700
defmethodpaint-block-atlas-relief
tile
eql:wood-side
xy

Wood bark: deep vertical grooves with grain between them.

let
groove
case
modx5
0-80
1-30
4-25
t20
defmethodpaint-block-atlas-relief
tile
eql:wood-end
xy

Wood end grain: raised concentric rings.

let*
dx
-x7.5
dy
-y7.5
ring
mod
floor
+
*dxdx
*dydy
18
defmethodpaint-block-atlas-relief
tile
eql:leaves
xy

Leaves: overlapping lobes with gaps between them.

defmethodpaint-block-atlas-relief
tile
eql:sand
xy

Sand: fine wind ripples over a soft dune.

defmethodpaint-block-atlas-relief
tile
eql:snow
xy

Snow: soft drifts with the odd crystal glint standing proud.

defmethodpaint-block-atlas-relief
tile
eql:crystal
xy

Crystal: sharp faceted planes meeting along the tile diagonals.

let
diagonal
anti
abs
-
+xy
15
block-atlas-byte
+110
*9
-8
mindiagonal8
*6
-8
minanti8
defmethodpaint-block-atlas-relief
tile
eql:terminal
xy

Terminal graphite: flat glass inside a raised per-block bezel.

defmethodpaint-block-atlas-relief
tile
eql:gravel
xy

Gravel: sharply varying grains at nearly every texel.

defmethodpaint-block-atlas-relief
tile
eql:clay
xy

Clay: compressed layers with very little loose grain.

defmethodpaint-block-atlas-relief
tile
eql:mud
xy

Mud: rounded wet clods interrupted by sunken pockets.

let
pocket
defmethodpaint-block-atlas-relief
tile
eql:moss
xy

Moss: soft overlapping cushions.

defmethodpaint-block-atlas-relief
tile
eql:cactus-side
xy

Cactus side: strong vertical ribs with standing spines.

block-atlas-byte
+118
case
modx5
0-55
15
248
35
t-28
if
zerop
mod
+
*x3
*y5
17
700
defmethodpaint-block-atlas-relief
tile
eql:cactus-end
xy

Cactus top: gently domed flesh inside a lower rind.

let*
dx
-x7.5
dy
-y7.5
radius
sqrt
+
*dxdx
*dydy
block-atlas-byte
+178
-
*radius8
if
>radius5.5
-350
defmethodpaint-block-atlas-relief
tile
eql:cobblestone
xy

Cobblestone: proud stones separated by recessed irregular joints.

if
or
zerop
mod
+x
*2y
7
zerop
mod
+
*3x
y
13
48
defmethodpaint-block-atlas-relief
tile
eql:stone-bricks
xy

Stone bricks: shallow-cut mortar around worn faces.

defmethodpaint-block-atlas-relief
tile
eql:bricks
xy

Fired bricks: deeper joints and rougher faces than stone masonry.

defmethodpaint-block-atlas-relief
tile
eql:planks
xy

Planks: recessed seams over gently ridged grain.

if
zerop
mody5
45
defmethodpaint-block-atlas-relief
tile
eql:sandstone
xy

Sandstone: broad sediment layers with granular faces.

block-atlas-byte
+136
case
mody7
0-42
1-18
514
t0
defmethodpaint-block-atlas-relief
tile
eql:slate
xy

Slate: thin raised sheets divided by sharp cleavage.

defmethodpaint-block-atlas-relief
tile
eql:turtle-skin
xy

Turtle skin: small tight pebbles all over the hide.

defmethodpaint-block-atlas-relief
tile
eql:turtle-plastron
xy

Turtle plastron: flat belly plates with narrow sunken seams.

The player's own body and what it holds are drawn the same way as the animals -- textured boxes on the block surface pipeline -- and paint their hide, sleeve, and gadgets from the same atlas. See BODY.LISP.

defconstant+player-skin-tile+:player-skin
defconstant+player-sleeve-tile+:player-sleeve
defconstant+phone-body-tile+:phone-body
defconstant+phone-screen-tile+:phone-screen
defmethodpaint-block-atlas-tile
tile
eql:player-skin
xy

Player skin: warm hide with the faintest knuckle mottling.

let
pebble
pack-block-atlas-rgba
+214
roundpebble9
+166
roundpebble8
+132
roundpebble8
defmethodpaint-block-atlas-tile
tile
eql:player-sleeve
xy

Player sleeve: a knitted teal cuff, ribbed along the arm.

let
rib
if
evenp
6-6
variation
shaded-block-atlas-pixel44112118
+ribvariation
defmethodpaint-block-atlas-tile
tile
eql:phone-body
xy

Phone body: matte dark metal, one even tone with no visible grain.

declare
ignorexy
defunphone-screen-icon-p
xy

Whether X,Y lies on one of the app icons in the phone screen's grid.

The tile is stretched over the whole screen, so its sixteen rows are the screen's height: a status bar along the top row, three rows of four icons, and a dock row at the bottom.

and
>=y3
<y13
let
column
modx4
row
mod
-y3
3
and
>=column1
<column3
<row2
defmethodpaint-block-atlas-tile
tile
eql:phone-screen
xy

Phone screen: a lit wallpaper gradient with a grid of little app icons.

defmethodpaint-block-atlas-relief
tile
eql:player-skin
xy

Player skin: soft, barely textured.

defmethodpaint-block-atlas-relief
tile
eql:player-sleeve
xy

Player sleeve: knitted ribs along the arm.

block-atlas-byte
if
evenp
150106
defmethodpaint-block-atlas-relief
tile
eql:phone-body
xy

Phone body: bead-blasted flat, the least relief a tile is allowed.

defmethodpaint-block-atlas-relief
tile
eql:phone-screen
xy

Phone screen: glass, flat but for the faintest bow across the pane.

+126

The urbit material arrived after the gadget and reel tiles, so its tile offset sits past them: tile order is history, not palette order, and the vocabulary domain alone decides which dense atlas lane a tile gets.

defunurbit-sigil-glyph-p
xy

Whether X,Y lies on the planet sigil: a ring crossed by its equator.

let*
dx
-x7.5
dy
-y7.5
radius
sqrt
+
*dxdx
*dydy
or
<=4.4radius5.9
and
<=7y8
<radius5.9
defmethodpaint-block-atlas-tile
tile
eql:urbit
xy

Urbit: a white planet sigil on a near-black field.

defmethodpaint-block-atlas-relief
tile
eql:urbit
xy

Urbit: the sigil stands proud of a matte face.

--------------------------------------------------------------------- The tape: a film reel, drawn flange-on and rim-on.

defunreel-radius
xy

Distance of texel X,Y from the tile's centre, in texels.

let
dx
-x7.5
dy
-y7.5
sqrt
+
*dxdx
*dydy
defunreel-spoke-p
xy

Whether X,Y lies on one of the three flange spokes laid over the film.

let*
dx
-x7.5
dy
-y7.5
angle
atandydx
loopforspokein'
1.57083.6652-0.5236
fordifference=
abs
-
mod
+
-anglespoke
pi
*2pi
pi
thereis
<
*difference
sqrt
+
*dxdx
*dydy
0.9
defunpaint-reel-flange
xylabel-p

A reel flange: dark corners, a bright rim, wound film showing between three spokes, a hub with a spindle. label-p paints a paper label on the film.

let
grain
block-atlas-variationxy:tape-flange
cond
>r7.6

The canister the reel sits in.

shaded-block-atlas-pixel444240
roundgrain4
>r6.6
shaded-block-atlas-pixel168166158
roundgrain3
>r2.4
cond
andlabel-p
<
abs
-y7.5
1.6
>x8
shaded-block-atlas-pixel226214178
roundgrain6
t

Wound film: dark sepia, faint concentric rings.

shaded-block-atlas-pixel624432
+
roundgrain4
if
evenp
roundr
6-6
>r1.1
shaded-block-atlas-pixel150148140
roundgrain4
defmethodpaint-block-atlas-tile
tile
eql:tape-flange
xy

Tape flange: an empty reel, film wound dark behind its windows.

defmethodpaint-block-atlas-tile
tile
eql:reel-rim
xy

Reel rim: two bright flanges with the wound film's edge between them.

let
grain
cond
or
<y2
>y13
shaded-block-atlas-pixel168166158
roundgrain3
or
=y2
=y13
shaded-block-atlas-pixel969490
roundgrain4
t

The film's edge, striated along the winding.

shaded-block-atlas-pixel584230
+
roundgrain4
if
evenpx
5-5
defmethodpaint-block-atlas-tile
tile
eql:film-flange
xy

Film flange: a loaded reel with a paper label across the film.

defmethodpaint-block-atlas-relief
tile
eql:tape-flange
xy

Tape flange: the rim and hub stand proud, the windows sink.

let
cond
>r7.6
96
>r6.6
176

The film's winding, a faint spiral of ridges.

>r2.4
+100
if
evenp
+xy
60
>r1.1
168
t60
defmethodpaint-block-atlas-relief
tile
eql:reel-rim
xy

Reel rim: flanges proud, the film between them lower and ribbed.

cond
or
<y2
>y13
176
or
=y2
=y13
130
t
if
evenpx
110104
defmethodpaint-block-atlas-relief
tile
eql:film-flange
xy

The birthday meadow's blooming grass. One tile: the grass top scattered with small four-petal flowers. Each bloom belongs to one 4x4 texel cell, so blooms never collide and the tiling stays unobtrusive.

defunflowers-top-bloom
xy

Return the bloom part covering texel X,Y, or NIL for plain grass.

Each 4x4 cell may host one five-texel flower: four petals around a warm centre, jittered inside its cell and coloured per cell.

let*
cell-x
cell-y
gate
when
>gate112
let*
jitter
bloom-x
+
*cell-x4
1
modjitter2
bloom-y
+
*cell-y4
1
mod
ashjitter-2
2
distance
+
abs
-xbloom-x
abs
-ybloom-y
cond
:center
case
0:pink
1:white
2:violet
t:blue
defmethodpaint-block-atlas-tile
tile
eql:flowers-top
xy

Blooming grass top: little bright flowers over the meadow green.

defmethodpaint-block-atlas-relief
tile
eql:flowers-top
xy

Blooming grass top: the grass top's tufts, each flower standing proud.

defunmake-block-texture-atlas

Return the little world's horizontal RGBA8 atlas as packed pixel words.

rgb is the material's procedural colour and A is opaque coverage. The array spans the full tile capacity; tiles past the painted count stay zero, waiting for a material to claim them.

defunblock-atlas-relief-at
tilexy

Read tile's relief with coordinates clamped to its own boundary.

defunpack-block-atlas-normal

Pack a signed tangent-space normal and its source height into RGBA8.

pack-block-atlas-rgba supplies opaque alpha; replace it with the inspectable height after reusing its channel encoding.

logior
logand
pack-block-atlas-rgba
*
+x1.0
127.5
*
+y1.0
127.5
*
+z1.0
127.5
#x00ffffff
defunpaint-block-atlas-normal
tilexy

Return tile's packed tangent-space normal at X,Y.

The normal is the central difference of the exact procedural relief painted beside the colour. Boundary reads clamp to the tile, so neither the generated map nor later texture filtering can borrow a neighbouring material's shape.

defunmake-block-normal-atlas

Return the relief-correlated tangent-space normal atlas as packed RGBA8.

rgb is a linear encoded unit normal and A is the procedural height from which it was derived. This is a derived materialization, not an authored asset.