> ## Documentation Index
> Fetch the complete documentation index at: https://blockscope.linvin.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Mesh geometry

# Color-Block Mesh Geometry

Phase 2A turns the Phase 1 `Scene` into a deterministic mesh. It uses an
original color palette and built-in full-cube geometry. No Minecraft textures,
models, or resource packs are required.

## Pipeline

```text theme={null}
Scene
  -> SceneBlockView
  -> ColorBlockCatalog
  -> MeshBuilder
  -> Mesh (16^3 pages)
  -> OBJ / PLY / statistics
```

## Coordinate System

* Scene world coordinates are signed `i64` block coordinates.
* A mesh page covers a 16x16x16 block region.
* `MeshPage.origin` is the page's world block origin as `i32`.
* Vertex positions are local to the page and stay in `0.0..=16.0`.
* This keeps `f32` precision stable even when the scene is far from the origin.
* Page assignment uses `div_euclid`, so negative coordinates work correctly.

## Mesh Contract

```text theme={null}
Vertex {
  position: [f32; 3],   // page-local
  uv:       [i16; 2],   // Q12 fixed point
}

Quad {
  vertices: [Vertex; 4],
  normal:   [f32; 3],
  color:    [u8; 4],    // straight alpha
  ao:       [u8; 4],    // 2-bit levels
  texture:  u16,
  layer:    opaque | cutout | translucent,
  shade:    bool,
}

Mesh {
  pages: [MeshPage],
  statistics: MeshStatistics,
}
```

Vertices are ordered counter-clockwise when viewed from outside the block. The
quad normal must agree with the winding; tests assert this with a cross product.

## Face Culling

For a face that lies on the block boundary:

1. If the neighbor position is outside the scene, keep the face.
2. If the neighbor is air, keep the face.
3. If the neighbor model fully occludes (full cube + opaque), cull the face.
4. If the neighbor is the same canonical block state, including partial
   shapes, cull the face. This removes internal faces between adjacent glass,
   water, ice, leaves, and matching partial shapes. The check is state-based,
   not a per-face coplanarity test.
5. Otherwise keep the face. Different translucent materials keep their
   interface faces.

Partial models use per-face cull directions and voxelized model occupancy.

## Color Catalog

`ColorBlockCatalog` resolves a canonical `BlockStateKey`:

* exact embedded palette entry;
* family heuristic (dye colors, wood types, ores, plants, glass, stairs/slab
  suffixes);
* magenta fallback with `known = false`.

The fallback is intentional: unknown blocks stay visible and are counted in
mesh statistics. Air resolves to an empty non-occluding model.

Default layers:

* `translucent`: water, glass, stained glass, ice, slime, honey;
* `cutout`: leaves, saplings, flowers, plants, rails, torches, ladders, panes,
  iron bars, chains, crops;
* `opaque`: everything else.

The palette is original approximate data under
`crates/mesh/data/color-palette.json`. It is not copied from Minecraft assets.

## Limits

`MeshLimits` defaults:

| Limit | Default |
| - | - |
| pages | 65,536 |
| quads | 5,000,000 |
| vertices | 20,000,000 |

Exceeding a limit returns `MESH_LIMIT_EXCEEDED` or `PAGE_LIMIT_EXCEEDED` and
exits with code 2 in the CLI.

## Exports

* **OBJ**: page-origin-adjusted vertices, normals, and quad faces.
* **PLY**: ASCII vertices with RGBA colors and quad faces. Useful for MeshLab,
  Blender, or other viewers.

Both exporters are deterministic: the same mesh produces identical bytes.

## CLI

For CLI invocation and mesh export options (`--obj`, `--ply`, `--json`), see
[CLI Reference - mesh](https://blockscope.linvin.net/user/en/cli.md).

## Partial Shapes

Phase 2B adds box-based shapes. Block state properties are read from the
canonical key:

| Family | Properties | Approximation |
| - | - | - |
| slab | `type=bottom/top/double` | exact box |
| stairs | `facing`, `half` | straight shape; corner `shape` values use straight geometry |
| carpet | none | 1/16 layer |
| snow | `layers=1..8` | 2/16 per layer |
| trapdoor | `half`, `open`, `facing` | closed panel or open side panel |
| door | `facing`, `open` | closed/open panel; hinge is ignored |
| fence | `north/east/south/west` | post + two bars per connection |
| fence gate | `facing`, `open` | post + gate panel |
| wall | `up`, connection sides | post + 8-wide arms |
| pane / iron bars | connection sides | center post + arms; isolated pane becomes a thin plane |
| button | `face`, `facing` | small floor/ceiling/wall box |
| pressure plate | none | 14x1x14 plate |
| torch | floor/wall name | small box, wall offset by `facing` |
| ladder | `facing` | thin side panel |
| rail | none | 16x1x16 plate |
| cactus | none | 14x16x14 box |
| cross plants | none | four quads (two crossed planes, double-sided) |
| water / lava | `level=0..15` | height `16-level`; level 0 is a full cube |
| chest / trapped / ender | none | 14x14x14 box |
| barrel / shulker box | none | 14x16x14 box |
| sign / banner | `facing` ignored | 2x16x16 panel |
| skull / head | none | 8x8x8 box |
| lectern | none | base plus top box |
| beacon | none | full cube, translucent layer |
| conduit | none | 8x8x8 box |

These are deliberately approximate. They preserve the silhouette and material
color; they do not try to reproduce every vanilla micro-detail. Block-entity
text, item contents, banner patterns, and skull skins are not rendered yet.

## Voxel Mesher

Model boxes are voxelized into a cached 16^3 occupancy grid. For each face
plane, exposed 1x1 cells are greedily merged into the largest rectangles. This:

* removes interior faces between overlapping or touching boxes;
* merges coplanar faces across box boundaries;
* emits `cullface` only for faces on the block boundary;
* caches the resulting model per canonical block state.

Full cubes bypass the voxel path and reuse the six-quad fast model. A model
whose boxes fill the complete 16^3 volume also collapses to the full cube.

## Same-State Culling

A boundary face is culled when the neighbor is:

* a full opaque cube;
* the same canonical block state, including partial shapes.

The second rule removes shared boundary faces of adjacent slabs, stairs,
fences, panes, glass, and water. It is state-based: stacked partial models can
lose an exposed face when their geometry does not meet at the same plane.
Different partial states keep their interface faces.

## Resource Packs

The `BlockCatalog` trait is implemented by both the original color catalog and
the resource-pack catalog (`litematic-material`). Pack models replace the
built-in shape when their blockstate/model resolves to elements; otherwise the
Phase 2 shape, the model `particle` texture, or the color palette is used.

Pack quads carry explicit UVs, a texture id, a tint, an optional per-quad layer,
and a shade flag. Texture coordinates follow Minecraft's face convention; chest
entity textures use the standard box unwrap. See `docs/textures.md` for the full
asset and fallback contract.

Block-entity text/icons, entity models beyond the built-in chest, and dynamic
item contents remain future work.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.