Blockbench & the .bbmodel format
What a .bbmodel file actually is, which format to start a project in, the element rules the game stopped enforcing in 1.21.6 and 1.21.11, and the gotchas that cost the most time — measured against the game's own models where a number is claimed.
- What a .bbmodel is, and is not
- Choosing a project format
- The element rules, and which ones still apply
- What the game reads, measured
- UV mapping: box vs per-face
- Bones, parenting and pivot points
- .bbmodel format versions & breaking changes
- Animation
- Handing a .bbmodel to a server plugin
- Gotchas
- Sources
What a .bbmodel is, and is not
.bbmodel is Blockbench's project format: a single JSON file holding the geometry, the UV map, the embedded textures, the animations, and the editor state for one project. It is a save file, not a game asset. Minecraft cannot load a .bbmodel; nothing in assets/ or data/ ever has that extension. What ships in a resource pack is the export — a Java block/item model JSON — and what ships to a server plugin is the .bbmodel itself, which the plugin converts.
That distinction is the source of the most common beginner failure: the model is finished, the file is in the pack, and the game renders nothing, because the file in the pack is the project rather than the export.
Blockbench's own documentation is explicit that .bbmodel is “mainly intended to be used as an internal format”, and recommends that anything building a model loader define its own format via a Blockbench plugin instead of parsing .bbmodel directly. The format has had breaking changes and carries a format_version field precisely so that consumers can cope with them — see .bbmodel format versions.
Two consequences worth knowing before you start:
- Everything is in the one file. Textures are embedded, so a
.bbmodelis self-contained and can be handed to someone else as a single attachment. This is why server plugins accept it directly. - The file you author is not the file you ship. A pack ships the exported JSON plus a separate PNG; a plugin ships the project. Keep the project in source control and treat the export as a build artefact.
Choosing a project format
Blockbench's format choice at project creation is not cosmetic — it decides which features the editor exposes and which restrictions it enforces. Choosing wrong and discovering it after a day of modelling is unpleasant, because format conversion is lossy in the direction that matters (a Generic model dropped into Java Block/Item loses whatever exceeds the Java limits).
| Format | Use it for | Exports | Key limits |
|---|---|---|---|
| Java Block/Item | Vanilla resource-pack blocks and items — the format for anything the vanilla renderer draws. | .json (java blockmodel), .obj, .gltf, .bbmodel | 3×3×3 block size limit; parent models supported; one cube rotation axis in the editor; integer-free cube sizing is not available. |
| Generic Model | Server-side model plugins (ModelEngine and friends), and anything that is going to be converted rather than loaded by vanilla. | .obj, .gltf, .bbmodel | Unlimited size and rotation; supports model animations and multiple textures; per-texture UV size. |
| Modded Entity | Fabric/Forge/NeoForge entity models. | .java, .obj, .gltf, .bbmodel | Box UV; bone rotations unlimited; no vanilla resource-pack path. |
| OptiFine Entity / Part | OptiFine CEM entity replacement. | .jem / .jpm, .obj, .gltf, .bbmodel | Expression-based animation; needs the CEM Template Loader plugin to edit and preview. |
| Bedrock Model | Bedrock Edition entities and attachables. | .json (bedrock geo & animation), .obj, .gltf, .bbmodel | Not loadable by Java Edition at all. |
| GeckoLib Model | Java mods using the GeckoLib animation library. | .json (bedrock animation), .obj, .gltf, .bbmodel | Requires the mod; not a resource-pack route. |
If the model is going into a resource pack, start in Java Block/Item and let the editor stop you from building something the exporter cannot represent. If it is going to a server plugin, start in Generic Model and name the file carefully — several plugins use the file name as the model's in-game id, so renaming it later means editing configuration that references the old name.
From an empty project to a model in the game
The rest of this page is about the file. This section is the part that stops people on day one: an empty Blockbench window has no obvious way to make anything, and the tool most people reach for first does not exist.
1. Pick the format before you build
The project format decides what the model can ever be — which export it produces, and whether it can animate. A Java Block/Item project can never hold keyframes, because vanilla Java has no animated block-model format. If you want motion, choose an entity or Generic Model format up front; converting later is not a button. See Choosing a project format.
2. Know which mode you are in
Blockbench has four working modes, switched from the tabs at the top: Edit, Paint, Animate and Display. Adding geometry is an Edit mode action, so if a project seems to offer no way to add anything, check which mode you are in before anything else.
3. Add geometry
There is no line tool and nothing that draws shapes in 3D. Blockbench builds models from elements, and the creation actions are the whole list: Add Cube, Add Mesh, Add Group and Add Texture Mesh. Which of them a project offers depends on its format. Start with Add Cube, then shape it with the Element panel’s Position, Size, Pivot Point and Rotation sliders, or drag it in the viewport.
Straight lines exist only when painting a texture: hold Shift with the Paint Brush or Eraser and it draws a line from the last point. There is no line icon to find, which is why looking for one fails.
4. Give it a texture
The Textures panel has Create Texture for a new blank sheet and Import Texture for an existing image. Paint in Paint mode, and read UV mapping before you start: box UV and per-face UV lay the sheet out differently, and switching later repaints nothing for you.
5. Set how it looks in a hand or a frame
Display mode positions the model for each slot it can appear in — first and third person, head, ground, item frame, GUI — against a reference model. Skip this and a correct model can still look wrong the moment someone holds it.
6. Get it into a pack
A Java Block/Item project exports a .json block model. That file goes
under assets/<namespace>/models/ in a resource pack with its textures
under assets/<namespace>/textures/, and on current versions an item
reaches it through an item model definition — see
Resource packs. The .bbmodel itself
stays behind as your working file; the game never loads it. A server-side model
plugin is the exception, and it is covered in
Handing a .bbmodel to a server plugin.
The element rules, and which ones still apply
Every modelling guide in the ecosystem teaches the same element rule: a cube may be rotated about one axis, by an angle from -45, -22.5, 0, 22.5, 45, and nothing else. That rule dates from 14w07a, when custom block models were first given rotation at all. It is no longer the game's rule.
- 1.21.6 (25w16a) — block model rotations are no longer limited to multiples of 22.5.
- 1.21.11 (25w46a) — elements can be rotated around multiple axes, and the restriction limiting the angle to the range
[-45, 45]is removed. - 26.1 (snapshot 7) — any block model can use cutout or translucent textures; the format of the
texturesmap changed. - 26.3 (snapshot 3) —
shade_direction_overrideadded to elements; theshadeproperty removed. - Before 1.21.6 — the classic rule holds in full, and a pack targeting older clients must still obey it.
This is not a paper change. In 26.3 Snapshot 10 the game's own models already use angles the old rule forbids: of 303 element rotations across 95 vanilla models, 10 fall outside the legacy set — seven at -67.5°, two at -90°, and one at 0.0001°. They are all sign templates.
| Angle | Elements | Legal before 1.21.6? |
|---|---|---|
45 | 131 | yes |
-45 | 70 | yes |
-22.5 | 49 | yes |
22.5 | 22 | yes |
0 | 19 | yes |
-67.5 | 7 | no |
-90 | 2 | no — outside [-45, 45] as well |
0.0001 | 1 | no |
Two rotation forms
The multi-axis change did not extend the old object; it added a second shape. Both are accepted, and vanilla currently uses both — 301 elements in the angle/axis form and 2 in the per-axis form.
assets/<namespace>/models/block/example.json — the classic form
"rotation": { "angle": -22.5, "axis": "y", "origin": [8, 0, 8] }
assets/<namespace>/models/block/example.json — the 1.21.11+ per-axis form
"rotation": { "x": 180, "y": -67.5, "z": -180, "origin": [8, 0, 8] }
Note what the second form does not contain: there is no axis field. An element either names one axis and one angle, or gives per-axis angles under x, y and z. Mixing the two in the same object is not a documented shape and should not be relied on.
The tool is now stricter than the game. Blockbench's Java Block/Item format still allows one cube rotation axis in the editor, and server-side model plugins still document the pre-1.21.6 rule as an absolute constraint, because they convert models into item models for clients that may be older. So a rotation the game accepts may still be unbuildable in your editor, or rejected by your plugin. Treat the classic rule as a toolchain constraint now, not a game one — and check the specific tool rather than assuming either way.
Coordinate range
Element from and to coordinates are clamped to -16 through 32 — one block of overhang in each direction around the 16×16×16 block volume. Vanilla stays inside it: across all 1,204 elements in the game's models, zero coordinates fall outside that range. A cube pushed beyond it does not error loudly; it is clamped, and the model silently renders wrong.
What the game reads, measured
An exporter writes what it knows; the vanilla loader reads what it recognises and ignores the rest. Reading the shipped models is the cheapest way to see where those two sets differ. All counts below are from 26.3 Snapshot 10 (resource pack format 97), across 4,192 model files, of which 347 define their own elements.
| Element key | Uses | Meaning |
|---|---|---|
from / to | 1,204 each | The cube's opposite corners. Required. |
faces | 1,204 | Per-face texture and UV. Required. |
shade_direction_override | 349 | Added 26.3 snapshot 3 26.3+, replacing shade. Already the second most common element key in vanilla. |
rotation | 303 | Either rotation form; 97 of them also set rescale. |
name | 114 | A human label. The renderer does not use it. |
__comment | 63 | Vanilla's own inline comments. |
light_emission | 4 | Per-element light emission 1.21.2+. |
shade | 0 | Removed in 26.3 snapshot 3; no longer present anywhere in vanilla. |
At the top level of a model file, the distribution shows how little of a pack is actually geometry: textures appears in 4,147 files and parent in 3,887, but elements in only 347. Most vanilla models are a parent reference plus a texture map. A pack that redefines geometry where it only needed to retexture is doing more work than the game asked for, and inherits none of the parent's later fixes.
Exporter leftovers
Two keys in vanilla's models are not vanilla model fields at all:
groups— the Blockbench outliner hierarchy, present in four block models (custom_fence_side_north,_east,_south,_west), each carrying a group object complete with Blockbench's"color": 0field.texture_size— present in exactly one model,heavy_core.json, set to[16, 16], which is the default.
Both are inert. They are visible proof that Mojang exports from Blockbench too, and they are a useful calibration: the vanilla loader ignores unknown keys rather than failing, which is why a stray groups array in your own export costs bytes but not correctness.
Strip groups, name and texture_size from exported models if pack size matters — on a pack with hundreds of models the outliner hierarchy is pure overhead. Do not strip __comment from models you expect others to maintain; vanilla keeps its own. See Ticking & performance for the broader pack-size picture.
UV mapping: box vs per-face
Blockbench offers two UV modes, and the choice constrains everything downstream.
| Box UV | Per-face UV | |
|---|---|---|
| How it maps | The cube is unwrapped automatically into a cross; all six faces are placed for you. | Each face has its own UV rectangle, set independently. |
| Used by | Entity models (Modded Entity, OptiFine, Bedrock), and available in Java Block/Item. | Java Block/Item and the vanilla renderer's native form. |
| Face rotation | Not supported. | Supported in Java Block/Item. |
| Survives a 90° rotate | No — box UV cannot preserve the mapping. | Yes — the mapping stays intact. |
| Multiple textures | Restricted. | Supported. |
Two rules keep a Minecraft-style model looking right:
- Preserve the pixel ratio. One texture pixel corresponds to one unit of model scale. A face whose UV rectangle does not match its geometry squashes or stretches the texture. Blockbench's Auto UV does this correctly for per-face mapping.
- Avoid mixels. A “mixel” is an element of mixed resolution — a cube smaller than one pixel, or an over-inflated one — so that the model shows two effective pixel sizes at once. The vanilla art style does not use them (with the narrow exception of slightly inflated elements on some models).
Rotating a selection by 90° in per-face UV mode preserves the mapping, so a symmetric part can be modelled once and rotated into place. In box UV mode it cannot, so rotate the bone instead of the cubes — the group carries its children without touching their unwrap.
Bones, parenting and pivot points
Blockbench's vocabulary is worth using precisely, because plugin documentation assumes it:
| Term | Meaning |
|---|---|
| Group | An organisational container for elements and other groups. |
| Bone | A group in a format that supports group rotation — i.e. a group you can animate. |
| Element | Anything in the outliner that is not a group. |
| Cube | Any cuboid element, whatever its dimensions — not only geometric cubes. |
| Plane | A cube with one dimension at zero, so it has two faces. |
| Locator | A dimensionless reference point — used to position particles, effects or attachment points. |
Parenting is placing one bone inside another so the child follows the parent. Build the hierarchy outward, from bones near the centre of the body to bones away from it: torso → arm → hand. A consistent naming convention pays for itself the moment a config file has to reference a bone by name.
Pivot points are the single most common cause of animation that looks wrong for reasons the author cannot name. A pivot belongs at the joint — the point of attachment between two bones — not at the centre of the geometry and certainly not left wherever it landed. Set it with the Pivot tool, or centre it to the selection from the Element panel, and set it on the group, not on a cube inside the group.
Blockbench's numeric sliders accept math expressions, not just numbers, and the expression is applied to each selected element separately. Typing math.random(-30, 30) into a rotation field randomises every selected cube independently; prefixing with *, /, + or +- operates on the existing value, and val or n stands for it. Entering *2 into a size field doubles every selection at once.
.bbmodel format versions & breaking changes
Every .bbmodel carries a format_version. Anything that reads these files should branch on it, because the format has broken compatibility more than once. Additions are not listed by Blockbench; only the changes that alter how existing data is interpreted.
| Version | Released with | Breaking change |
|---|---|---|
| 5.0 | Blockbench 5.0, 12 October 2025 | Groups and the outliner hierarchy became separate fields: groups holds the groups, outliner holds the hierarchy without group data. |
| 5.0 | Blockbench 5.0, 12 October 2025 | Keyframe value direction was fixed. Values had been inverted on the X axis for position keyframes, and on the X and Y axes for rotation keyframes. From 5.0 they are not. |
| 4.10 | Blockbench 4.10, 9 May 2024 | Relative texture paths were being saved relative to the .bbmodel file as if it were a directory; they are now correctly relative to the directory containing it. |
| 4.10 | Blockbench 4.10, 9 May 2024 | The name field is now ignored and overwritten with the file name when a project is loaded from a file. |
| 4.10 | Blockbench 4.10, 9 May 2024 | In formats with a default texture, textures are no longer written per face unless explicitly assigned to that face. |
| 4.9 | Blockbench 4.9, 2 December 2023 | In generic models and other formats with per_texture_uv_size, UV size became a per-texture value rather than a global one. |
The 5.0 keyframe fix inverts old animations. A model animated before Blockbench 5.0 encodes position-X and rotation-X/Y keyframes in the old, inverted convention. Blockbench itself migrates on load, but any external consumer that reads .bbmodel files — a server plugin, a converter, a custom importer — will produce mirrored motion if it applies the new convention to an old file or vice versa. The symptom is characteristic and easy to misread as an animation authoring error: a swing or step that plays backwards while everything else looks correct. Check format_version before blaming the animation.
Animation
Animation is a per-format capability, not a universal one. Model animations are available in Bedrock Model, Bedrock Legacy, Modded Entity, OptiFine Entity (via expressions), Generic Model and GeckoLib — and not in Java Block/Item, because vanilla Java has no animated block-model format. Animating a resource-pack model means either the item-definition system, display entities, or a server-side plugin; it does not mean keyframes in the model file.
Where animation is available, the mechanics are consistent:
- Keyframes are drawn as diamonds for linear interpolation and circles for smooth. Step keyframes hold. Bezier keyframes exist, but consumers vary in whether they interpolate them.
- Channels are per-bone and per-property (rotation, position, scale). Only bones can be animated; elements cannot.
- The playhead snaps to valid frame times by default; hold Ctrl to scrub smoothly.
Minecraft ticks 20 times per second, so an animation destined for the game is ultimately sampled at 20 fps. Set Animation Snap to 20 under File → Settings → Snapping so the timeline moves in 0.05 s steps and every keyframe you place lands on a tick boundary. Keyframes placed between ticks are not wrong, but they are not what the server will play.
Handing a .bbmodel to a server plugin
Server-side model plugins take the opposite route from a resource pack: you give them the .bbmodel project, and they generate the resource pack for you by splitting the model into per-bone item models. The Codex documents this in detail on the ModelEngine page; the parts that are really modelling decisions belong here.
- Bone count is entity count. Each bone that contains geometry becomes a rendered entity in the world. A model with sixty bones costs sixty entities per spawn. Bones with no geometry are virtual and cost nothing, so the balance to strike is between cubes (free) and bones (expensive but animatable).
- Bone names are an interface. Prefixes and reserved names change behaviour — head tracking, seats, hitboxes, nametag anchors. A rename is an API change, so settle the naming before anyone writes config against it.
- Orientation and ground level are conventions. Model facing north, feet on the grid: the grid line is ground level, and a model built floating will spawn floating.
- The hitbox is modelled, not configured. A dedicated hitbox bone supplies both the collision box and the eye height, taken from that bone's pivot Y. A pivot at or below zero produces a mob that takes damage for no visible reason — it is suffocating.
Because these plugins generate item models for the client, the cubes inside your bones inherit the vanilla item-model restrictions as the plugin implements them — which, for current releases, still means the pre-1.21.6 rule of one rotation axis and an angle from the classic set. The bones themselves rotate freely. So the practical division is: put unrestricted rotation in the bone, keep the cube legal. This is why a Generic Model that looks fine in Blockbench can still fail conversion.
Gotchas
| Symptom | Cause | Fix |
|---|---|---|
| The pack loads but the model does not appear. | The .bbmodel was copied into the pack instead of the exported JSON. | Export the Java block/item model; ship that, plus the texture as a separate PNG. |
| Flickering, striped faces where two cubes meet. | Z-fighting: coplanar or near-coplanar faces sharing a depth value. | Move one cube out of the conflict, or inflate/deflate one of them so they stop sharing the plane. |
| Visible seams or hairline cracks between parts. | Vertices that are close but not identical. | Use Vertex Snap — pick a vertex on the cube to move, then the vertex to meet. It also works as a tape measure: select one vertex, hover another, read the distance in the status bar. |
| An animation plays mirrored or backwards after a tool upgrade. | The Blockbench 5.0 keyframe direction fix, applied across the version boundary. | Check format_version; migrate the file rather than re-authoring the animation. See format versions. |
| Texture appears squashed or stretched on one face. | The UV rectangle does not match the face's geometry. | Per-face UV: use Auto UV on that face. Box UV: the unwrap is automatic, so the cube's dimensions are what changed. |
| The model looks “off” in a way nobody can name. | Mixels — elements below 1 px, or over-inflated ones, putting two effective resolutions on screen at once. | Bring every element back onto the pixel grid; if detail will not fit at 16×16, the detail is not necessary. |
| A part rotates around the wrong point. | The pivot is at the geometric centre, or was never moved. | Put the pivot at the joint, and set it on the group rather than a child cube. |
| A rotation the wiki says is legal will not go in. | The editor or the conversion pipeline still enforces the pre-1.21.6 rule. | Rotate the bone instead of the cube, or target the newer form directly in the exported JSON. |
| Work lost to a crash. | — | Blockbench auto-backs-up every 10 minutes by default; Help → Open Backup Folder. The interval is a setting. |
| Something failed and there is no message. | The error went to Blockbench's own console. | Ctrl+Shift+I, then the Console tab. |
| An item model looks wrong in the inventory only. | The GUI display slot is using the wrong lighting. | GUI offers side light (for models shown at an angle, like vanilla blocks) and front light (for models facing the viewer). Pick the one matching the rest of the inventory. |
| An exported model is far larger than expected. | Outliner metadata (groups, per-element name) written into the export. | Strip it — the vanilla loader ignores those keys. Vanilla itself ships four models that forgot to. |
Licensing
Blockbench is free and open source, for any purpose including commercial. Its documentation is explicit that what you make with it is your artwork and yours to redistribute — the tool claims nothing. That is a statement about Blockbench, not about the assets you feed it: a model traced from someone else's work, or built on a purchased asset, carries whatever licence that source came with.
Mojang uses Blockbench internally for Minecraft's own models — the axolotl, goat, camel and sniffer among them — and supports its development. That is the reason the vanilla asset shape and the Blockbench data model line up as closely as they do, and why exporter leftovers turn up in the game's own files.
Sources
- Blockbench Wiki — The .bbmodel format — format intent,
format_version, and the 4.9 / 4.10 / 5.0 breaking changes. - Blockbench Wiki — Formats — the per-format capability matrix this page's format table is drawn from.
- Blockbench Wiki — Overview & Tips — terminology, pivot points, parenting, vertex snap, Z-fighting, sliders and expressions.
- Blockbench Wiki — Minecraft Style Guide — element count, UV ratio, mixels, shading conventions.
- Blockbench Wiki — FAQ — licensing, Mojang's internal use, backups, the console.
- Blockbench Wiki — 3D Export — OBJ / glTF / FBX / DAE trade-offs for non-Minecraft targets.
- Minecraft Wiki — Model — the version history behind the 14w07a, 1.21.6, 1.21.11, 26.1 and 26.3 rotation and element changes.
- ModelEngine — Creating a Model — bones vs cubes, hitbox and eye height, ground level and facing.
- ModelEngine — Animating a Model — 20 fps snapping and keyframe interpolation support.
- misode/mcmeta — assets-json — the shipped models every measured count on this page was taken from, via
tools/model_shape_audit.py.