Voxel fields and chunk windows
The seam is shared spatial meaning, not shared ownership #18MPLA
Luvcraft now has the right evidence for a spatial vocabulary to become more than an attractive analogy. Block content, derived light, live meshing neighborhoods, immutable worker snapshots, collision, and streaming all inhabit the same chunked voxel world. They should not become one object, but neither should each of them reconstruct what a cell address, local offset, neighbor, face, and chunk crossing mean.
The duplicated arrays are not the deepest problem. Separate fields often should be separate because they have different producers, owners, revisions, and storage. The architectural seam is that several such products currently rebuild the spatial substrate beneath those differences.
This is the first concrete client of the more general domain/bundle account in #D5M8BZ. It also sharpens that account: Bundle is not the whole missing abstraction. The useful decomposition is:
voxel space how cell addresses and physical positions relate finite domain which local sites and storage offsets belong to one patch field product which distributed fact is materialized over those sites chunk window how a local query continues into other materializations provenance which incarnations and revisions justify the result
The aim is not to make the engine advertise advanced mathematics. It is to let lighting code speak about lighting, meshing code speak about surfaces, and physics code speak about bodies while sharing one honest account of where their data lives.
Mentioned in: The first Lisp atelier should stay ordinary
Mathematical ideas should improve the questions, not burden the names #EQ6GLY
Affine lattices, combinatorial topology, covers, sheaves, order-theoretic lattices, and discrete exterior calculus are useful sources of distinctions. They draw attention to placement, adjacency, incidence, locality, overlap, restriction, partial knowledge, and values associated with cells or faces. That does not yet earn those terms as source-level abstractions.
The implementation vocabulary can remain ordinary:
voxel-space chunk-domain chunk-window neighbor boundary-crossing voxel-field field-materialization field-kernel
"Chunk window" is a particularly useful hacker-facing name for the part that resembles a cover or atlas. It says that an operation has a finite local view onto a larger chunked world without claiming a precise mathematical structure the implementation does not provide.
Likewise, today's cells and six-neighbor steps do not justify a general topological-space protocol. If future fluid or geometry work places values on faces, edges, and vertices and consumes explicit incidence operations, a cell complex or cochain vocabulary may then be earned by a real calculation.
Mentioned in: The repository became clearer by becoming less grand
Addressing and metric are two sides of voxel space #KV001P
The voxel world has a discrete addressing side:
- an integer triple names a cell;
- primitive directions identify face neighbors;
- a world address decomposes into chunk address plus local address; and
- a finite chunk maps local addresses to dense offsets.
It also has a physical metric side:
- a cell has an extent;
- a cell address maps to a physical point;
- an address difference maps to a physical displacement; and
- face area, cell volume, and step length follow from the extent.
voxel-space already contains both a chunk shape and a cell-extent, and
world-coordinate-cell-origin performs the first explicit address-to-position
map. The distinction should become more pervasive rather than disappear into
one universal kind of neighborhood.
Voxel light is step-based: an ordinary six-neighbor move loses a gameplay
light level regardless of how many metres one cell represents. Physics is
metric: velocity, acceleration, collision extents, and timestep require
physical quantities. A diffusion stencil may need both adjacency and a
spacing-dependent influence. Moppe's TerrainDomain is useful evidence: its
four neighbors carry inverse-area influences, so a generic Laplacian derives
the right physical dimension without knowing the grid spacing itself.
The shared concepts should therefore remain distinct:
| Concept | Answers |
|---|---|
| neighbor relation | Which sites are adjacent? |
| step displacement | What physical displacement separates them? |
| neighborhood policy | Which adjacent or nearby sites does this operation use? |
The current mesher and player simulation appear to treat one cell as one
metre even though voxel-space admits another extent. That is a hypothesis to
verify during the bridge work, not a settled bug claim. The durable rule is
that a discrete cell address is not itself a metre-valued world position; the
space performs that interpretation explicitly. #M8W6RP already records the
corresponding quantity distinction.
Vec3 is a representation, not one spatial meaning #7K8UBF
The luvcraft source contains several visibly three-component families, but an audit shows that they should not all become the same abstraction:
| Family | CPU representation | Meaning lives in |
|---|---|---|
| cell, chunk, and local addresses | distinct integer structures | nominal coordinate type |
| primitive face steps | voxel-direction | displacement type and six shared values |
| camera/player positions and velocity | vec3 | owning slot or function name |
| ray, camera basis, and sun direction | vec3 | operation and argument name |
| colours | simple vectors | sky/color calculation |
| mesh attributes and shader values | specialized arrays and :vec3 lanes | vertex layout and shader quantity metadata |
The vec3 structure in LUV.ARITHMETIC.LISP.VEC3 is therefore
deliberately modest. It bundles continuous CPU components, supplies component,
scale, dot, cross, length, and normalization operations, and extends the open
Lisp arithmetic protocol without making that protocol name the representation.
LUVCRAFT.WORLD imports it but does not own or re-export it. The representation
does not claim that a point is a velocity,
that either is already measured in metres, or that an RGB triple belongs to
spatial algebra. camera-position and player-velocity name different
semantic owners even though both use the same transparent representation.
That distinction gives the readable code the useful part of structification:
camera and player objects no longer maintain parallel x, y, and z slots;
rays no longer accept arbitrary sequences; camera basis and shadow calculations
no longer duplicate positional list arithmetic; persistence converts a vec3
to an external list only at the file boundary. Axis-specific collision and
voxel traversal still use component accessors where the axis is the algorithm.
This also keeps the allocation claim narrow. A retained camera position or
velocity naturally has indefinite extent. A short-lived vec3 may use the
same inline-constructor and dynamic-extent technique documented in #B3UEVE,
but the migration does not require every vector calculation to prove zero
allocation before earning a readable value type.
Mentioned in: Bundle continuous spatial triples
Referenced from code:defstruct (vec3
(:constructor %make-vec3 (x y z))) vec3.lisp:8 ↗
A chunk domain owns local traversal, not world truth #E4T0PD
A chunk-domain should be the one place that knows the finite patch's local
shape and storage order. Its useful operational vocabulary is approximately:
domain-cardinality domain-index / domain-offset do-domain-sites step-domain-site do-domain-face
step-domain-site should report either another local site or a boundary
crossing. It should not decide that crossing the east face reaches air,
stone, open sky, an unloaded chunk, or an error. Those are facts or policies
of the environment in which the domain is being used.
Nor should one neighborhood become intrinsic to every chunk calculation.
Lighting wants six face neighbors; ambient occlusion wants side and diagonal
samples; meshing wants a face neighbor plus corner stencils; collision wants
the cells intersecting a volume. The domain supplies primitive traversal and
boundary facts. Explicit policies assemble the neighborhoods algorithms
actually mean, following the separation that survived in Moppe's
bundle_operations.hh (#E4N7PX).
Coordinates should be ordinary nominal values throughout the code, including dense traversal. The distinction worth preserving is not "objects outside, components inside" but lifetime: a queue or hash key needs an indefinite-extent coordinate, while a loop-local coordinate can have dynamic extent. Compiler-visible iteration macros can provide the latter without a heap allocation or a per-cell call across a compilation-unit boundary.
That requirement applies to adjacency as well as whole-domain and face iteration. A function which returns a fresh neighboring coordinate has to give it indefinite extent before its caller can decide whether to retain it. The useful hot-path shape is therefore a macro which binds one dynamic-extent destination around the consumer body; only a consumer which actually enqueues the destination copies it. Crossing arithmetic remains the domain's job, window lookup still occurs only for a crossing, and the caller still supplies the neighborhood policy.
Mentioned in: Minecraft contains several families of frontier work, Keep rejected neighbors at dynamic extent
Referenced from code: Execute Execute DIRECTIONS is the caller's explicit neighborhood policy. DESTINATION has
dynamic extent on each iteration and must be copied before defmacro with-chunk-domain-step world.lisp:334 ↗
body for one primitive step from local inside domain.offset, DESTINATION, and CROSSING are bound as by step-chunk-domain-site, but
DESTINATION has dynamic extent and must be copied before body retains it. The
compiler-visible lifetime keeps rejected adjacency probes off the heap. #E4T0PDdefmacro do-chunk-window-neighbors world.lisp:449 ↗
body for the DIRECTIONS neighboring LOCAL through WINDOW.body retains it.
Interior steps remain domain arithmetic; window dispatch occurs only at an
actual chunk crossing. #E4T0PD
Coordinate values can be stack-temporary #B3UEVE
SBCL's stack-allocation rules make defstruct a good fit for the small
spatial values in this layer. A user-defined structure can be stack allocated
when its defstruct constructor was declared inline before the definition
and the receiving binding is declared dynamic-extent. The declaration is a
lifetime promise, not an analysis result: the value must not escape through a
queue, hash table, closure, return value, or retained callback argument.
The manual's x86/x86-64 limitation concerns structures with raw slots. SBCL defines those as particular unboxed float, complex-float, or word slots, and explicitly excludes fixnums from the category. The coordinate structures use ordinary tagged integer slots, so this limitation does not apply on the current ARM64 target.
The live SBCL 2.6.7 image confirms the distinction under the project's
ordinary compiler policy (all qualities at 1). In otherwise identical
one-million-iteration loops, an ordinary three-integer coordinate structure
reported 48,182,016 bytes through sb-ext:get-bytes-consed, while the
dynamic-extent structure reported 0. A three-element Common Lisp
vector declared dynamic extent likewise reported 0. After warm-up, the
actual do-chunk-domain-sites macro traversed 4,096,000 coordinate values and
reported 0 bytes consed.
A three-dimensional coordinate certainly has vector-shaped representation,
but not every such value has vector semantics. A world coordinate is an
affine cell address, a chunk coordinate names another lattice, a local
coordinate is bounded by a domain, and a voxel direction is a displacement.
Using four defstruct types retains those distinctions and named accessors;
using bare Common Lisp vectors would collapse them back into positional
components. Dense storage remains in specialized arrays. These structures
name the small values used to address that storage, and dynamic extent makes
their short lifetime explicit where it matters.
Mentioned in: Vec3 is a representation, not one spatial meaning, Give dense traversal coordinate values
Referenced from code: Execute LOCAL is a DYNAMIC-EXTENT LOCAL-COORDINATE and must not be retained after
defmacro do-chunk-domain-sites world.lisp:581 ↗
body for every site in DOMAIN, in dense storage order.body returns. This gives dense algorithms a nominal coordinate without one
heap allocation per site. See #B3UEVE.
A chunk window continues a local domain #YUBB7X
A local domain can say that a step crossed its boundary. A chunk window answers what spatial materialization, if any, can continue the query:
flowchart LR A["local site"] --> B["domain step"] B -->|"stays local"| C["local offset"] B -->|"crosses a face"| D["chunk window"] D --> E["neighbor materialization"] D --> F["open / closed / unknown"] D --> G["unavailable"]
The window reports availability; the subsystem interprets it. Lighting may distinguish open sky, closed world, and unknown terrain. Meshing may treat an absent sample as air, solid, or an error. Physics may treat unknown support as solid or suspend a body. Ecology may call the reading unavailable rather than zero. Moving those choices into the domain would turn streaming state into terrain truth.
Different windows need not share one representation. They need a small
aggregate protocol for operations such as locating a cell, resolving a
boundary crossing, and borrowing a requested field product. Field-specific
facades such as sample-block-at and sample-light-at can remain readable
interfaces above that mechanism.
Mentioned in: A glance is an image and the small truth that frames it
Referenced from code: Execute DESTINATION has dynamic extent. MATERIALIZATION and AVAILABILITY are selected
through defmacro with-chunk-window-step world.lisp:411 ↗
body for one domain step continued through window when necessary.locate-chunk-window-site only for a boundary crossing. #YUBB7X
The current program already contains four windows #WUB581
The proposed vocabulary names structures that already work:
| Current structure | Window it provides | Spatial work it currently owns |
|---|---|---|
block-world | live resident world | coordinate decomposition, resident lookup, absent status |
block-mesh-neighborhood | resolved 3\times3\times3 window | relative chunk decomposition and repeated dense offsets |
block-mesh-snapshot | immutable one-cell halo | explicit halo domain, expanded coordinates, and one fixed columnar materialization |
light-region | eager or lazy solver atlas | boundary-only region resolution, entry-local offsets, and lazy entry capture |
The duplication is visible in current source rather than inferred from equal
array lengths. light-region-locate remains the cold adapter from retained world
coordinates, but propagation and unlighting retain an entry and local site,
then use continue-chunk-window-site so interior neighbors stay in domain
arithmetic. map-entry-face-sites delegates face offsets to
do-chunk-domain-face. In luvcraft/mesher.lisp, block and light access through
the resolved neighborhood share relative decomposition and offset arithmetic,
while the immutable snapshot shares one block-mesh-halo-domain and generated
columnar materialization across content-code, sky-level, and block-level
storage (#LC5ULQ).
This is an unusually good refactoring target because the algorithms around the arithmetic are already distinct and tested. The work can remove spatial duplication while leaving light propagation, AO sampling, face visibility, snapshot ownership, and stale-result rejection recognizable.
Mentioned in: Phase 2: make voxel light an explicit derived field
Field identity, value meaning, and representation are independent #FKAV5Y
A field definition says which distributed fact one column represents. Its value quantity says what a reading at one site means. Its representation says how those readings are stored. These are three different identities.
For example, sky light and block light are different fields: they have different sources and may have different invalidation rules. They may also use distinct named quantity specifications. Both currently occupy u8 arrays, but equal representation makes neither the fields nor their values interchangeable.
Conversely, two field roles may deliberately carry the same quantity specification while remaining separate columns. One semantic light value could also be represented as constant zero, a packed nibble, u8 levels, normalized float, SIMD-expanded floats, or a GPU lane without changing the field's meaning.
A first field definition might need only:
field identity site kind value quantity specification default or missing-value meaning legal range or encoding representation policy
A field materialization then binds that definition to a finite domain and actual storage. Product-wide revisions, boundary revisions, and stability state belong to the materialization or its owning derived product, not to every site value.
Block opacity exposes why these distinctions matter. The atlas's normalized
:opacity is a rendering proportion. block-light-opacity is documented as
a 0..15 propagation cost. Calling both opacity does not make them one
quantity. A field experiment should probably rename the latter meaning to
something like propagation loss or light-step cost before using arithmetic
typing to bless an accidental equivalence.
Referenced from code: One distributed fact's identity and per-site meaning. #FKAV5Y The inherited represented-value declaration describes a reading after its
storage encoding has been resolved. REPRESENTATION-POLICY separately names
the aggregate encoding, such as a palette-index column or a u8 level array.defclass voxel-field-definition world-fields.lisp:10 ↗
Domain, materialization, and revision have different identities #HAUW7L
A chunk removed and reinstalled at the same chunk coordinate covers the same spatial domain, but it is not the same resident materialization. A field can then change several times within that incarnation. Luvcraft's same-key replacement tests already rely on this distinction when withdrawing the old chunk's propagated light.
At least three identities must therefore remain visible:
domain identity which sites these are materialization identity which resident incarnation supplies them revision identity which version of its fields was observed
Bundle compatibility checks domain identity rather than equal cardinality. A mesh, collider, or light publication proof additionally records the materialization incarnations and field revisions it observed. Folding all three into one "domain version" would erase the correctness property the current stale-result machinery carefully preserves.
This is also why one universal voxel bundle is the wrong endpoint. Block content, voxel light, fluids, and ecological readings can be sibling materializations over compatible domains while retaining their own owners and validity conditions (#A6X2RT).
Field kernels bridge domains to semantic arithmetic #ADR040
Luv's arithmetic work already has the layers this design needs:
luv.arithmeticowns dimensions, units, named quantity meanings, tensor order, and point/absolute/difference character;luv.arithmetic.languageowns backend-neutral checked definitions and expression graphs;luv.arithmetic.lisplowers one such definition to an ordinary compiled Lisp function over raw numbers and vectors; and- the shader language adds GPU interfaces, resources, and target lowering around that same arithmetic substrate.
Shaders therefore do not own meaningful arithmetic. They are one realization of it. The missing bridge says:
This field carries this value meaning over these sites in this representation; choose one checked operation and run it over borrowed storage.
A field kernel should connect field definitions to a checked arithmetic definition, select a scalar or wide realization once, borrow the arrays, and then run an ordinary loop or worklist without per-cell CLOS dispatch.
flowchart TB A["field definitions + finite domains"] --> B["checked kernel boundary"] C["arithmetic definition"] --> B B --> D["borrowed raw arrays"] B --> E["scalar / SIMD / GPU realization"] D --> F["closed loop or worklist"] E --> F
This is the Lisp analogue of Moppe storing mp-units values in typed Bundle columns, but it need not copy the C++ technique. Inspectable definitions and aggregate checks can keep the semantic information outside unboxed runtime lanes, as #B5L7VG anticipates.
Physics is the obvious next numerical client, but not another reason to add columns to a universal voxel record. Collision traversal should remain domain/window code which enumerates occupied cells and constructs contacts; integration, acceleration, and eventual impulse laws can be checked arithmetic over body fields. Bodies and contacts then retain their own finite domains as #Y5H8KC describes, while the block world remains the static environment they query.
Mentioned in: Declarations keep representation and quantity parallel, Share one production computation between CPU and GPU, Frontier programs are compiled sparse kernels
Lighting should use a checked local law, not become an arithmetic graph #WEE8P5
The light solver is the best first proof because it already separates block content, two light fields, palette-derived attenuation and emission tables, boundary availability, fixed-point work, publication, and revision tracking.
The arithmetic DSL should describe a local transfer law, not the entire algorithm. In rough form one edge computes:
candidate = attenuate(source level, propagation loss, direction) destination = max(destination, candidate)
Chunk lookup, residency, queues, removal waves, scheduling, publication, and revision tracking remain lighting control structure. The chunk window supplies the destination site; field materializations supply typed storage; the checked local law computes one influence; the worklist decides when to visit again.
There is an open semantic choice at the CPU/mesh boundary. The stored 0..15
level may be only an encoding of a normalized light proportion, making
division by 15 a representation conversion. Or one gameplay light step may
be a meaningful scaled dimensionless unit, making the propagation rule and
conversion to :one explicit arithmetic. "Lose one level per ordinary
step" is currently a game rule, so the second reading is plausible, but the
first field experiment should force and record the decision rather than hide
it in u8 storage.
If ordinary subtraction cannot truthfully express attenuation, add a named
operation such as attenuate-light through the open EQL-specialized operator
protocol. Do not weaken - until two differently named integers happen to
type-check.
Mentioned in: Frontier programs are compiled sparse kernels
The fixed-point algebra should wait for a second client #BA9MCA
Light has two lattice-like structures. Its sites form a spatial lattice under
six-neighbor adjacency. Its levels form a finite order in which max is the
join. From-scratch propagation repeatedly joins attenuated neighbor
contributions until it reaches a fixed point. Incremental removal first
over-removes a region, then rebuilds the monotone closure from surviving
sources.
That suggests a later reusable shape:
worklist fixed point domain and window input and output fields sources neighborhood policy edge transfer join
Distance transforms, reachability, influence propagation, or ecological fields might eventually share it. Extracting this solver before a second client would be a framework searching for evidence. Domain stepping, window resolution, field meaning, and kernel boundaries already have multiple real clients and should come first.
The sheaf-like interpretation should remain similarly informal. Chunks are local patches, halos resemble restrictions, and snapshots collect compatible local readings. But core chunk domains do not overlap, residency introduces unknown values, and lighting solves a nonlocal equation rather than merely gluing existing answers. "Field materialization" and "chunk window" are more operationally exact today.
The later source study #NXXOQT supplies another kind of evidence: a small Haskell engine in which BFS, A*, and Cheney collection share explicit frontier, memo, admission, and two-phase materialization roles. The terminal-wall component in #K3PCP3 is now a deliberately simpler adjacency client beside lighting. Together they narrow the reusable target to packed frontier storage and iteration laws while leaving fixed-point relaxation as one client-owned policy.
Mentioned in: Columnar layout, materialization, and policy are separate, Discover, relax, and invalidate are three different dynamics, Pack the lighting worklist, then test level scheduling
Chunk hierarchy and level of detail are related but not identical #TDEVBM
A residency hierarchy groups the same underlying cells into chunks, regions, or superchunks for lookup, persistence, scheduling, and invalidation. It does not necessarily make the world coarser.
Level of detail introduces different sites or different field meanings. A coarse site may carry occupancy fraction, dominant material, surface bounds, average radiance, or conservative collision information rather than one categorical block state. #O3P8NV develops why its schema may differ as well as its spacing.
An octree can host either concern, which is why they are easy to conflate. The semantic test is:
- same cells grouped into larger administrative regions means hierarchy;
- different sites carrying a coarser description means level of detail.
A later hierarchical window may resolve a request from an ordinary resident chunk, an ancestor cache, or a coarse materialization. Local algorithms need not know the lookup structure, but the returned field meaning, resolution, and confidence must remain honest.
Not everything spatial is a voxel field either. Moisture, temperature, smell, or habitat suitability may be cell fields. A critter is more likely a persistent entity carrying a position, perhaps indexed by spatial buckets. Vegetation can have both density fields and individual nearby plants. These systems can share voxel-space and chunk-window protocols without sharing one storage abstraction.
The Lisp shape is semantic objects around dense data #M0REWV
The idiomatic arrangement follows the project's existing CLOS practice:
- EQL-specialized symbols name field definitions, quantity definitions, and arithmetic operations;
- CLOS instances represent voxel spaces, chunk domains, chunk windows, materializations, policies, and derived products;
- generic dispatch selects a representation or kernel at a chunk or phase boundary;
- specialized arrays and closed loops remain visible inside that selection; and
- thin definition macros appear only when repeated ordinary methods reveal a pleasant definition site.
The first experiment should not begin with bundle-class. Ordinary
inspectable field definitions attached to the existing block-content and
light columns can reveal what metadata and redefinition behavior are actually
needed. A metaclass becomes useful only if real definitions repeatedly want
class-level schema, allocation, migration, and inspector support.
Live redefinition adds one requirement that Moppe gets from C++ compilation:
a materialization must know which field-definition revision made its bytes
meaningful. Redefining :sky-light must either remain representation
compatible, visibly invalidate existing arrays, or migrate them. It must not
silently reinterpret live storage. Compiled kernels likewise need dependency
revisions and last-known-good replacement, following the existing shader
discipline.
A staged concretization #BA1QCS
The following is a sequence to refine from evidence, not a Gantt chart.
- State the value vocabulary. Complete #9ZK7Q7 so luvcraft's existing amounts and points stop relying on use-site annotations. Decide whether a gameplay light step is a unit or a storage encoding; distinguish propagation loss from texture opacity.
- Extract local spatial operations. Give
chunk-domainheap-allocation-free world/chunk/local decomposition, primitive stepping with boundary results, storage-order traversal, and face enumeration. Migrate light-region and meshing paths without changing their algorithms.
- Name the window protocol. Let the live world, resolved meshing
neighborhood, immutable halo, and light-region atlas resolve locations or
crossings through their existing representations. Preserve semantic
facades such as
sample-block-atandsample-light-at.
- Attach ordinary field definitions. Describe the existing block-content, sky-light, and block-light columns without changing their arrays. Keep field identity, value quantity, representation, product state, and provenance distinct.
- Share one production calculation. Refine #D1R2NK with a domain-shaped client. Light decoding or a named light-response law is modest; a transfer law is more revealing if both CPU tooling and a shader genuinely use it.
- Earn a field kernel. Once one scalar field operation is stable, select its representation once and run it over borrowed arrays. A native SIMD realization follows a real measured kernel (#VKLLPR), not the vocabulary design.
Each step should delete a concrete duplication or make a concrete mistake unrepresentable. None requires a universal bundle, a generalized fixed-point solver, a sheaf API, per-cell objects, or a broad rewrite of the working light system.
DONE Make chunk traversal one owned vocabulary #K3KZTG
Intent: establish the smallest reusable spatial substrate beneath the current
light and meshing products. Add heap-allocation-free decomposition, primitive
local stepping with explicit boundary crossings, storage-order site
enumeration, and face enumeration to chunk-domain or one narrowly related
voxel-domain protocol. Rewrite light-region-locate,
map-entry-face-cells, the resolved meshing-neighborhood accessors, and halo
capture to consume those operations while retaining their representations and
policies.
Evidence: voxel-space-decompose-components owns Euclidean decomposition,
while chunk-domain owns offset inversion, local-to-world mapping, primitive
stepping with explicit chunk crossings, storage-order enumeration, and face
enumeration. World, chunk, local, and direction values now give that
substrate one nominal vocabulary rather than parallel positional triples.
light-region-locate and map-entry-face-sites no longer contain their own
division, dense-offset, or face-plane formulas. Light seeding and boundary
re-entry consume domain site traversal and primitive stepping. The resolved
meshing neighborhood now has one locator shared by block and light reads; the
snapshot has one halo-offset operation shared by capture and both field
accessors. Six cached origin/extent slots disappeared from each snapshot,
while the world, light region, neighborhood, and snapshot remain separate
inspectable representations.
The full make test suite passes, including vertical and lateral light seams,
open/closed/unknown boundaries, randomized incremental/reference equality,
same-key replacement, stale mesh products, and immutable halo equivalence.
make smoke produces edc597168a3ec79a04c6d2af53c5b1a5, byte-identical
to the render from starting commit b9fa93d.
Done: one owned domain vocabulary now supplies local traversal to both lighting and meshing. No field schema, metaclass, generalized solver, or per-cell object was introduced to obtain the deletion.
Mentioned in: What this page does not decide, Phase 2: make voxel light an explicit derived field
Referenced from code: Resolve one nearby world site to its resident chunk and dense offset. The 3x3x3 window owns availability; voxel-space and chunk-domain own the
decomposition and storage order beneath it. See #K3KZTG.defun block-mesh-neighborhood-locate mesher.lisp:233 ↗
DONE Give dense traversal coordinate values #R3T7YA
Intent: replace the positional x y z and dx dy dz protocols exposed by
the first extraction with nominal coordinate and direction values. Make
dense iteration a macro so those values can be constructed and consumed at
the call site, and distinguish its borrowed dynamic-extent values from the
coordinates lighting intentionally retains.
Evidence: do-chunk-domain-sites and do-chunk-domain-face expand closed
storage-order loops whose local coordinates are declared dynamic-extent.
The mesher's visibility and emission passes consume those values directly.
Lighting propagation queues, removal records, dirty-cell sets, arrival and
departure sets, region keys, face seeding, and boundary re-entry now carry
world-coordinate, chunk-coordinate, local-coordinate, or
voxel-direction values according to meaning. A retained coordinate is
copied out of a dynamic-extent traversal value deliberately.
The current ARM64 stack-allocation evidence is recorded in #B3UEVE. The focused world suite passes 14 tests and the full luvcraft suite passes 41, including reference-light convergence, chunk seams, same-key replacement, stale mesh products, and immutable halo equivalence.
Done: the compiler-visible dense path and the readable nominal path are now the same path. Components remain available through accessors at arithmetic leaves; they are no longer the protocol repeated across lighting and meshing.
DONE Bundle continuous spatial triples #7A5HI4
Intent: replace the parallel camera/player position and velocity components, ad hoc ray sequences, and local camera-basis vector helpers with one small continuous CPU representation. Preserve nominal integer coordinates and directions, semantic shader quantities, packed mesh lanes, and colours as different concepts and representations.
Evidence: fly-camera owns one camera-position value; block-world-player
owns player-position and player-velocity values; raycasting requires a
vec3 origin and direction; cell extent and address-to-position mapping use
vec3; the sun and camera basis share the same elementary vector operations.
Block-face normals now reuse voxel-direction instead of becoming generic
vectors. Persistence retains its portable list form at the external boundary.
The source audit and boundary rationale are recorded in #7K8UBF. The focused
world suite passes 15 tests and the full luvcraft suite passes 42. A camera
with double-float CPU components is explicitly covered at the single-float GPU
uniform boundary. The standalone smoke render is SHA-256
0562804c1a3a4aaed5cc2865d0ca556b92ca231ab339f3310b21a8515b07d2c0,
byte-identical to the render from starting commit 07bf2ed.
Done: related continuous components travel together through the CPU code while the program still says which triples are addresses, directions, colours, and GPU representations.
DONE Name the chunk-window protocol #L84JCX
Intent: expose the shared aggregate operation already visible in the live
world, resolved meshing neighborhood, immutable halo snapshot, and light-region
atlas. Give those four concrete representations a small protocol for locating
a world site or resolving a domain crossing, while keeping availability
distinct from each subsystem's absent/open/closed/unknown policy. Preserve
sample-block-at and sample-light-at as readable field-specific facades.
Evidence to gather:
- a fifth window-shaped client can participate by adding methods rather than editing a type switch or copying coordinate arithmetic;
- the four existing windows remain independently inspectable and retain their current storage and ownership;
- dense light and meshing paths retain stack-temporary coordinate values and do not acquire a new per-cell CLOS decision merely to share lookup; and
- the light, meshing, production, and deterministic smoke evidence remains unchanged.
Done when: location and crossing continuation have one honest protocol across the four current windows, subsystem policy remains in semantic facades, and at least one remaining window-specific lookup duplication is deleted.
Evidence: locate-chunk-window-site now reports only a materialization,
representation-owned offset, and :available or :unavailable. Methods on
block-world, block-mesh-neighborhood, block-mesh-snapshot, and
light-region retain their hash table, resolved 27-chunk vector, halo arrays,
and lazy atlas respectively. continue-chunk-window-site performs pure
chunk-domain arithmetic for an interior step and dispatches to the window
only when the step crosses; its test adds a fifth recording window by one
method and proves that interior traversal never asks it.
The field-specific sample-block-at and sample-light-at facades still own
the meaning of absence. Hot neighborhood, snapshot, and light-region paths
call representation-specific inline locators rather than nesting a new CLOS
decision per sample. The snapshot locator now supplies both block and light
sampling, deleting their duplicated halo-presence test, while
light-region-locate-components shares scalar decomposition with the public
window method and avoids the old temporary local-coordinate value. The
luvcraft suite exercises all four windows, boundary continuation, meshing,
lighting, production, and deterministic world behavior.
The lighting runtime now carries light-region-entry plus a retained
local-coordinate in both addition and removal frontiers. An exact regression
records zero locate-chunk-window-site calls for an interior six-neighbor visit
and one call for a site on one face, for both propagation and unlighting.
World coordinates remain the identity of dirty and removed cells only at the
colder reconciliation boundary. Each entry retains its chunk-domain;
publication compares faces with do-chunk-domain-face, including a non-cubic
3\times4\times5 test, and light-region's redundant width, height, and depth
caches are gone.
On the fixed 27-chunk, seed-121 SLY fixture, five warmed solves still visit
214,056 sites. Median consing fell from 87,965,440 to about 74.9 million bytes
(about 15%), while median elapsed time rose from 0.178 seconds to 0.198--0.208
seconds on the same machine. A sampled run placed 9 of 18 inclusive samples
in continue-chunk-window-site, so this round records an allocation win and a
boundary-lookup invariant, not a latency win. The focused luvcraft suite
passes 58 tests, strict parinfer accepts every touched Lisp file, and a smoke
capture from the production SLY image remains byte-identical at
edc597168a3ec79a04c6d2af53c5b1a5.
Mentioned in: Bindings close a program over storage, Keep rejected neighbors at dynamic extent
Referenced from code: Step Return the destination OFFSET, wrapped LOCAL-COORDINATE, and crossing as
deftest compiled-light-drain-allocates-nothing-per-relation light-tests.lisp:344 ↗
defun continue-chunk-window-site world.lisp:567 ↗
local and resolve window only when the step crosses domain.step-chunk-domain-site does, followed by the neighboring MATERIALIZATION and
its AVAILABILITY. A local step returns NIL and :local for the last two values.
The one generic window decision therefore occurs only at an aggregate
boundary, never for every site in a dense traversal. #L84JCX
DONE Keep rejected neighbors at dynamic extent #KRU4RZ
Intent: make the lifetime distinction in #E4T0PD visible to SBCL while preserving the chunk-domain and chunk-window boundaries from #L84JCX. A six-neighbor visit should use one body-scoped destination at a time and copy a coordinate only when the algorithm retains that destination.
Evidence: with-chunk-domain-step exposes local stepping without returning its
temporary, with-chunk-window-step adds crossing-only window resolution, and
do-chunk-window-neighbors takes an explicit direction sequence. The lighting
addition and removal paths now retain a destination only when they enqueue it;
boundary reseeding uses the same body-scoped step. The old
step-chunk-domain-site and continue-chunk-window-site functions remain as
colder adapters which deliberately copy their result.
On SBCL 2.6.6, the fixed seed-121 81-chunk solve still performs exactly 2,430,167 worklist visits. Before this change it took about 1.79 seconds and consed 863.6 MB; three post-change solves each took 1.23 seconds and consed 264.1--264.2 MB. Thus rejected adjacency coordinates accounted for roughly 600 MB and a third of this fixture's elapsed time, without accounting for any of the repeated fixed-point work.
Done when: interior visits perform no window lookup, one-face visits perform
one lookup, explicit copies survive subsequent iterations, lighting results
remain unchanged, and the full test and deterministic smoke evidence pass.
The complete make test path passes, including SPIR-V validation and all luv,
luvcraft, and wiki suites. Two standalone smoke builds produced the identical
SHA-256
0c85d4550638418cb88d507c6541a49147aeeea5697175d13904942b65a689ec.
DONE Pack the lighting worklist, then test level scheduling #QS1ERH
Intent: remove the retained frontier's per-item list cell, light-region-site,
and copied local-coordinate without prematurely extracting the general
fixed-point algebra discussed in #BA9MCA. Represent a lighting site densely as
a region entry plus domain offset, while iteration reconstructs only a
dynamic-extent local value.
Evidence gathered:
light-workliststores entry, domain offset, and level in parallel reusable vectors. Pop clears the entry lane before reducing the logical length; an exact test checks LIFO order, brighter-first order with LIFO ties, reuse of the same backing vector, and absence of retained entries after emptying.- Addition, removal, open-boundary reseeding, arrivals, and emitter reseeding all exchange packed sites. A local coordinate is reconstructed with dynamic extent only while visiting one popped site.
- The unchanged-order variant isolates representation from scheduling, while the sixteen-bucket variant consumes the highest available level first.
The fixed seed-121 81-chunk solve produced these three-run ranges on SBCL 2.6.6:
| Frontier | Seconds | Consed | Visits |
|---|---|---|---|
| retained structs and conses | about 1.23 | 264.1--264.2 MB | 2,430,167 |
| packed LIFO | 1.245--1.265 | 31.8 MB | 2,430,167 |
| packed level buckets | 0.180--0.181 | 13.3 MB | 340,050 |
Packing therefore removed about 232 MB without improving latency: the former LIFO order, not allocation alone, caused the repeated fixed-point work. Level scheduling reduced the solve to about 1.03 visits per resident cell and is now the default for both reference and incremental lighting. On the same 81-chunk world, initial incremental settlement took 0.240 seconds and 487,321 visits; placing one crystal then reconciled in 0.001 seconds and 1,213 visits, changing five chunks.
Done when: lighting frontiers allocate no coordinate structure or cons per item, the unchanged-order variant isolates that allocation win, the scheduling experiment records both visits and elapsed time, and tests establish identical published light fields. A reusable solver protocol still waits for a second real client as in #BA9MCA.
Done: direct LIFO-versus-level coverage compares every sky and block array;
the incremental suite covers edits, removal, arrivals, departures, unknown and
open boundaries, and randomized agreement with the reference solver.
The complete make test path passes, and the standalone smoke render remains
byte-identical at SHA-256
0c85d4550638418cb88d507c6541a49147aeeea5697175d13904942b65a689ec.
The measured packed representation now supplies the first client for the
dynamic columnar-buffer design in #Y0TPND; #LDP5UR keeps that storage
extraction distinct from a generalized solver.
Mentioned in: Columnar layout, materialization, and policy are separate, Frontier is an operational pattern, not merely a queue
Referenced from code: Make the reference solver's packed LIFO or level-scheduled worklist. This machinery belongs to the test-only voxel-light oracle. Both modes
retain ENTRY plus dense OFFSET and LEVEL lanes, never a cons or coordinate
object per item. #QS1ERH #LDP5URdefun make-light-worklist light-reference.lisp:43 ↗
DONE Pay checked adjacency cost once per visited site #FGT96H
Intent: preserve checked public domain stepping while avoiding the same bounds and coordinate type validation for each of a trusted worklist site's six neighbors. The packed frontier already proves its entry and offset; adjacency should validate that site once, then keep primitive steps inside the checked scope.
Evidence: do-chunk-site-neighbors is the trusted-scope counterpart of
do-chunk-window-neighbors. It validates the domain and the popped offset
once, binds the shape's dimensions, the chunk coordinate, and the site's
components as fixnums, and steps each direction with primitive floor
arithmetic; no coordinate object is built and the window is consulted only
at a crossing. The compiled frontier kernel (#716UN6) now emits it for
every popped site, while step-chunk-domain-site, continue-chunk-window-site,
and the checked neighbor macro keep their public validation for arbitrary
callers. A test walks every site of a 4 by 3 by 5 chunk with both macros
and requires identical offsets, crossings, materializations, and
availabilities. Light fields and visits are unchanged against both oracles;
on the nine-chunk little world the compiled solver's median fell from
20.3 ms to 6.1 ms against the legacy solver's 23.9 ms, and a batch of forty
solves from 813 ms to 242 ms. The old profile's chunk-domain-offset entry
is gone from the compiled kernel; the remaining sampled cost sits at chunk
crossings, where the light region's locate-chunk-window-site still
resolves a coordinate key at about 275 ns and 58 bytes per crossing, some
ten thousand times per solve.
Done when: a hot neighborhood visit validates its source once without weakening step-chunk-domain-site or arbitrary callers, the crossing-only window invariant and light fields remain exact, and the same profile records whether the removed checks produce a material latency change. All hold.
Mentioned in: Voxel efficiency requires translating the algebra, not its objects, Bindings close a program over storage, Compile the monotone light kernel to scalar Lisp
Referenced from code: Emission. The generated loop is deliberately plain: raw bucket vectors
and counters are bound once at entry and written back at exit; the source
site's lanes and field values are bound once per pop; the popped site is
validated once and its six relations are primitive fixnum steps
( Map every arithmetic parameter to the emitted form holding its value. Eager fields are read once into a variable; lazy fields lower to their read
form wherever the law mentions them. Execute This is the trusted-scope counterpart of defun compilation-lowering-environment frontier.lisp:1073 ↗
do-chunk-site-neighbors, #FGT96H); a target's lanes are the source's own
for a local step and are borrowed from the crossing materialization
otherwise. Nothing per relation is generic, checked twice, or allocated.deftest trusted-site-neighbors-agree-with-checked-window-steps world-tests.lisp:448 ↗
do-chunk-site-neighbors validates a site once and steps primitively;
it must expose exactly the offsets, crossings, and window results of the
checked do-chunk-window-neighbors at every site of a small domain,
consulting the window only at crossings. #FGT96Hdefmacro do-chunk-site-neighbors world.lisp:473 ↗
body for the DIRECTIONS neighboring the site at SITE-OFFSET.do-chunk-window-neighbors for a
site already proved to belong to DOMAIN, such as one popped from a packed
frontier. DOMAIN and SITE-OFFSET are validated once; the shape's dimensions
and the site's components are then bound as fixnums, and each direction is a
primitive step with no coordinate object and no repeated bounds or type
check. offset is the destination's dense offset, CROSSING the direction when
the step leaves DOMAIN, and MATERIALIZATION with AVAILABILITY are selected
through locate-chunk-window-site only for a crossing. Public stepping keeps
its checks; this scope pays them once per visited site. #FGT96H
DONE Attach existing voxel field definitions #SIYGXO
Intent: describe the existing block-content, sky-light, and block-light columns without changing their representations or conflating field identity, per-site quantity, aggregate encoding, product state, and provenance.
Evidence: luv.world.fields owns a small voxel-field-definition which is
also a backend-neutral represented-value declaration. A definition names its
field and site kind, value type and optional quantity, unavailable-value
semantics, legal value type, aggregate representation policy, source form, and
identity token. :block-content remains a palette-u16 categorical field.
:sky-light and :block-light share u8 level storage but carry distinct
:sky-propagation-level and :block-propagation-level quantities; attempting
to substitute their declarations fails even though their representations are
equal.
Existing block-content-column and chunk-light-field objects retain the
definition identities current when their arrays are materialized. The
light-region-entry capture and immutable block-mesh-snapshot copy those
identities with their bytes. materialized-field-current-p makes live
redefinition visibly stale by object identity rather than silently
reinterpreting old arrays. Product revision and boundary stability remain on
their existing owners, and every per-site lane remains an unwrapped u16 or u8.
The subsequent percolation in #1RF48O makes the representation side equally
explicit. materialized-field-representation reaches the aggregate storage
from a field owner, while field-representation-domain reaches the finite
site domain from that storage. These are deliberately separate from
materialized-field-definition: meaning, representation, domain, and product
lifecycle remain four inspectable relationships rather than one overloaded
"field object."
The focused world and luvcraft tests exercise definition redefinition, categorical content, distinct light quantities, and propagation of definition identity through live light fields, atlas entries, and worker snapshots.
Mentioned in: Audit quantity-bearing Lisp storage
((offset destination crossing) domain local direction &body body)Execute BODY for one primitive step from LOCAL inside DOMAIN. OFFSET, DESTINATION, and CROSSING are bound as by STEP-CHUNK-DOMAIN-SITE, but DESTINATION has dynamic extent and must be copied before BODY retains it. The compiler-visible lifetime keeps rejected adjacency probes off the heap. #E4T0PD
(domain local direction)Step from one local site in a primitive face direction. Return the destination OFFSET and wrapped LOCAL-COORDINATE, followed by DIRECTION when the step crosses into that adjacent chunk or NIL when it stays inside DOMAIN.
(domain local)Addition over compatible quantities.
(x y z)Multiplication and scalar scaling.
Logical conjunction of tests and raw truth values.
Logical negation of one test or raw truth value.
The componentwise absolute value of a raw value.
((offset destination crossing direction materialization availability
window domain local directions &optional result)
&body body)Execute BODY for the DIRECTIONS neighboring LOCAL through WINDOW. DIRECTIONS is the caller's explicit neighborhood policy. DESTINATION has dynamic extent on each iteration and must be copied before BODY retains it. Interior steps remain domain arithmetic; window dispatch occurs only at an actual chunk crossing.…
((offset destination crossing materialization availability)
window domain local direction
&body body)Execute BODY for one DOMAIN step continued through WINDOW when necessary. DESTINATION has dynamic extent. MATERIALIZATION and AVAILABILITY are selected through LOCATE-CHUNK-WINDOW-SITE only for a boundary crossing. #YUBB7X
((offset local domain &optional result) &body body)Execute BODY for every site in DOMAIN, in dense storage order. LOCAL is a DYNAMIC-EXTENT LOCAL-COORDINATE and must not be retained after BODY returns. This gives dense algorithms a nominal coordinate without one heap allocation per site. See #B3UEVE.
(window x y z)Resolve world site X,Y,Z through WINDOW. Return (VALUES MATERIALIZATION OFFSET AVAILABILITY). AVAILABILITY is :AVAILABLE or :UNAVAILABLE; field and subsystem policy must interpret that fact rather than making the spatial protocol call absence air, solid, zero, or open sky. Implementations keep their existing…
(domain local-x local-y local-z)One distributed fact's identity and per-site meaning. #FKAV5Y The inherited represented-value declaration describes a reading after its storage encoding has been resolved. REPRESENTATION-POLICY separately names the aggregate encoding, such as a palette-index column or a u8 level array.
One represented value's machine form and optional semantic meaning. The representation type and quantity judgment are deliberately parallel: two declarations may both use VEC3 while denoting different quantities, and one quantity may acquire different representations in different backends. #OXBSAY
(neighborhood x y z)Resolve one nearby world site to its resident chunk and dense offset. The 3x3x3 window owns availability; voxel-space and chunk-domain own the decomposition and storage order beneath it. See #K3KZTG.
(space x y z)Decompose a world site into chunk and local scalar components. Return CHUNK-X, CHUNK-Y, CHUNK-Z, LOCAL-X, LOCAL-Y, and LOCAL-Z without constructing coordinate objects. Euclidean division keeps every local component non-negative, including for negative world coordinates. This is the dense traversal counterpart of…
Subtraction or unary negation.
Test whether one compatible scalar is at most another.
(dx dy dz)(domain x y z)(field-name)(realization &key (initial-capacity 256))(world &key immutable-p)Capture every resident chunk of WORLD for a from-scratch relight. With IMMUTABLE-P, copy content indices and capture absent-boundary semantics; the returned region may then be solved without reading the live world.
(realization input frontier)(realization region frontier execution &key key entry)((observation) &body body)Measure time, allocation, GC time, and collections while executing BODY. OBSERVATION is reset in place and BODY's values are preserved. SBCL's byte and GC clocks are process-wide; in a multithreaded image this deliberately attributes concurrent runtime activity during the observed extent too.
(realization window frontier execution &rest arguments)Run the compiled program until FRONTIER is empty; return EXECUTION. ARGUMENTS are the program's constants as keywords. A program whose family hands sites to a companion frontier, such as invalidation's surviving sources, takes that frontier as the first argument before the keywords.
Test whether one compatible scalar is greater than another.
Test whether one compatible scalar is less than another.
(window domain local direction)Step LOCAL and resolve WINDOW only when the step crosses DOMAIN. Return the destination OFFSET, wrapped LOCAL-COORDINATE, and crossing as STEP-CHUNK-DOMAIN-SITE does, followed by the neighboring MATERIALIZATION and its AVAILABILITY. A local step returns NIL and :LOCAL for the last two values. The one generic window…
(&key (scheduling :lifo) field-definition)Make the reference solver's packed LIFO or level-scheduled worklist. This machinery belongs to the test-only voxel-light oracle. Both modes retain ENTRY plus dense OFFSET and LEVEL lanes, never a cons or coordinate object per item. #QS1ERH #LDP5UR
Logical disjunction of tests and raw truth values.
(name)Return the inspectable physical row layout named by NAME.
(definition &optional declarations)Bind concrete represented DECLARATIONS to DEFINITION's physical lanes. DECLARATIONS is an alist from lane names to represented-value declarations. Representation compatibility and duplicate semantic ownership are checked once; returned rows retain the concrete declarations without wrapping values.
((offset crossing direction materialization availability
window domain site-offset directions &optional result)
&body body)Execute BODY for the DIRECTIONS neighboring the site at SITE-OFFSET. This is the trusted-scope counterpart of DO-CHUNK-WINDOW-NEIGHBORS for a site already proved to belong to DOMAIN, such as one popped from a packed frontier. DOMAIN and SITE-OFFSET are validated once; the shape's dimensions and the site's components…
(compilation &key (source-p t))Map every arithmetic parameter to the emitted form holding its value. Eager fields are read once into a variable; lazy fields lower to their read form wherever the law mentions them.
Test whether two compatible scalars are equal.
(lowered role offset-variable)(&key (id (gensym "BLOCK-WORLD-"))
(chunk-width 16)
(chunk-height 16)
(chunk-depth 16)
(cell-extent 1d0)
source)(world x y z)(domain)(domain offset)(&key (code t))(site)(site)(site)Headings, paragraphs, figures and their IDs, mentions, marks.
The little block world began with CLOS because generic functions, inspection, class redefinition, and multiple dispatch are unusually pleasant tools for a live engine. A later interest in structure-of-arrays storage can sound like a retreat from that object-oriented view: if data belongs in columns, were the objects…
The following is a vocabulary sketch rather than a frozen catalogue: Counts, indices, and categorical codes should not acquire physical units just because they are represented by integers. Conversely, converting a chunk coordinate and local cell coordinate into a world position should pass through an explicit metric…
Moppe's current spatial::Bundle is an eager, finite store of typed columns over one domain. The durable storage contract is deliberately small: – the domain supplies cardinality and checked index/offset conversion; – every declared quantity specification occurs once; – each field has one contiguous native vector; –…
Intent: make the dynamic lighting buffer one storage policy over reusable columnar layout metadata, add a fixed domain-bound policy, and prove the split with the meshing snapshot rather than a synthetic universal bundle. Evidence: columnar-layout-definition now describes physical lanes and row meaning independently of…
One universal voxel bundle would combine values with very different causes and invalidation rules. A more legible arrangement might eventually include: – a mandatory block-content bundle; – a derived or incrementally maintained light bundle; – an optional fluid bundle; – ecological or geological readings over their…
Moppe stores quantities in typed Bundle columns. Étalon's Bundle(Domain, Row) experiment used Zig's MultiArrayList to prove a related point: a row schema can retain semantic quantity specifications while the physical data is columnar. It rejected a raw f64 field in the bundle schema even though the underlying…
The domain/bundle vocabulary was developed for terrain, but its real claim is broader: a finite domain identifies sites, and fields have values over those sites (#B8R3KF). Box3D, read in this vocabulary, is a physics engine built from exactly such domains — with the twist that domain membership is dynamic: – The…
The small Haskell repository mbrock/frontier at 1688ab1 asks why breadth-first numbering, A* search, and Cheney copying garbage collection can all become instances of one short program. Its answer is more specific than “they use a worklist.” Each computation combines: – an unfolder which reveals adjacent work…
A planar rectangle of adjacent terminal-material blocks is a useful discover-once client. Starting from a placed or changed block face, the pass can traverse coplanar face neighbors of the same material, reserve a candidate surface identity, and collect bounds and membership. It then validates that the bounding…
Level of detail is not always the same field sampled less frequently. Exact block content is categorical; averaging stone and air does not produce a half-stone block. A coarse domain may need fields such as: – occupied volume or coverage; – minimum and maximum surface elevation; – dominant and secondary material; –…
Intent: with the character algebra inert-by-default (#SYUACW), make the block-world vocabulary state its truth: :opacity, :ambient-occlusion, :sky-light-level, :block-light-level, :material-emission, :fog-amount, :day-factor, :linear-rgb, :view-distance, :world-distance, and :shadow-filter-radius are non-negative…
Intent: make definition sharing answer a real engine question rather than only demonstrate two toy evaluators. Evidence: fog shaping is a small scalar candidate; the :world-to-light map is a richer candidate already used by production shaders and useful to CPU tests and tools. The latter should follow the…
Intent: eventually let a field or simulation phase select a scalar or SB-SIMD realization of the same semantic operation once per dense kernel. Evidence: #B5L7VG and the native SIMD study describe the representation seam, and #LDP5UR now supplies generated quantity-aware SoA storage. The first executable probe uses…
Light has two lattice-like structures. Its sites form a spatial lattice under six-neighbor adjacency. Its levels form a finite order in which max is the join. From-scratch propagation repeatedly joins attenuated neighbor contributions until it reaches a fixed point. Incremental removal first over-removes a region,…
The packed lighting frontier in #QS1ERH is the first small dynamic relative of a bundle. Its current sites are the ordinal domain [0, length); pushing and popping changes membership, while three parallel arrays materialize one entry, offset, and level reading for every member. The level buckets decide which buffer…
compile-frontier-program takes the definition, one frontier-field-binding per role, and a site-domain template. A binding names the represented-value declaration that gives the field its quantity and Lisp type (for light, the :sky-light voxel field definition and the light-opacity slot declaration), the lanes it…
Intent: make the fixed materialization vocabulary describe the ordinary resident and captured voxel fields too, and transfer palette-backed block content as one representation rather than as an accidental pair of arrays. Evidence: resident chunk-light-field objects and captured light-region-entry objects now retain…
The luvcraft source contains several visibly three-component families, but an audit shows that they should not all become the same abstraction: The vec3 structure in LUV.ARITHMETIC.LISP.VEC3 is therefore deliberately modest. It bundles continuous CPU components, supplies component, scale, dot, cross, length, and…
A chunk-domain should be the one place that knows the finite patch's local shape and storage order. Its useful operational vocabulary is approximately: step-domain-site should report either another local site or a boundary crossing. It should not decide that crossing the east face reaches air, stone, open sky, an…
SBCL's stack-allocation rules make defstruct a good fit for the small spatial values in this layer. A user-defined structure can be stack allocated when its defstruct constructor was declared inline before the definition and the receiving binding is declared dynamic-extent. The declaration is a lifetime promise, not…
A local domain can say that a step crossed its boundary. A chunk window answers what spatial materialization, if any, can continue the query: The window reports availability; the subsystem interprets it. Lighting may distinguish open sky, closed world, and unknown terrain. Meshing may treat an absent sample as air,…
A field definition says which distributed fact one column represents. Its value quantity says what a reading at one site means. Its representation says how those readings are stored. These are three different identities. For example, sky light and block light are different fields: they have different sources and…
Intent: establish the smallest reusable spatial substrate beneath the current light and meshing products. Add heap-allocation-free decomposition, primitive local stepping with explicit boundary crossings, storage-order site enumeration, and face enumeration to chunk-domain or one narrowly related voxel-domain…
Intent: expose the shared aggregate operation already visible in the live world, resolved meshing neighborhood, immutable halo snapshot, and light-region atlas. Give those four concrete representations a small protocol for locating a world site or resolving a domain crossing, while keeping availability distinct from…
Intent: remove the retained frontier's per-item list cell, light-region-site, and copied local-coordinate without prematurely extracting the general fixed-point algebra discussed in #BA9MCA. Represent a lighting site densely as a region entry plus domain offset, while iteration reconstructs only a dynamic-extent…
Intent: extract the synchronized specialized storage proven by the lighting frontier into a generated columnar-buffer substrate, while making its physical lanes and concrete row quantity declaration inspectable. Keep level scheduling, spatial stepping, and fixed-point behavior in lighting. Evidence:…
Intent: preserve checked public domain stepping while avoiding the same bounds and coordinate type validation for each of a trusted worklist site's six neighbors. The packed frontier already proves its entry and offset; adjacency should validate that site once, then keep primitive steps inside the checked scope.…
A warmed drain over pre-grown frontier storage allocates only at chunk crossings, where the window resolves a coordinate key (#L84JCX), never per site or per relation. The proof world exposes about 68,000 relations and 4,000 crossings; one cons per relation would exceed a megabyte.