Basic Modding - Model Files

Goal

I want to show you everything important about Minecraft 1.8 model files.

Difficulty

2/10 - Quite simple

Prerequisites

  • You should have some items or blocks to which you have applied a model

Forge Version

This Tutorial was created with Forge 11.14.1.1334 for Minecraft 1.8. If anything doesn't work with other versions, please contact me!


Model files in general

A model file in Minecraft 1.8 is basically a list of cuboids that have a certain position, size, rotation and texture. A model definition file either has a parent or a set of cuboid definitions, not both at a time. Model files with a parent can only redefine textures, not the 3D structure.


In the model file of Items, also the transformation of the model is saved. This includes rotation, translation and scale, depending on whether the Item is hold in the hand or rendered as an item.

Model files: children of parents

The easiest way to create a model file is by extending a parent file. Then, the whole 3D structure of the parent is copied (it cannot be modified!) and only the textures have to be changed. We already used this simple way of using models, namely when we created our first block. There, the model file looked like this:

models/block/TutorialBlock.json:
{
    "parent": "block/cube_all",
    "textures": {
        "all": "tutorial:blocks/tutorial_block"
    }
}

This file does several things:

First, it imports the 3D structure from "block/cube_all".

This is a reference to the file "assets/minecraft/models/block/cube_all.json". In this file, a cube is defined. Every face of this cube has the texture "all". This texture is set to a special texture here, namely "tutorial:blocks/tutorial_block".

This, however, is a reference to "assets/tutorial/textures/blocks/tutorial_block.png", which is out image. This image is now mapped on the block's faces from every side, as it is defined in cube_all.json.

Remember: Paths defined in a model file

The path in the "parent" tag is resolved as follows:

First, if the String does not contain a ':', the String "minecraft:" is used as a prefix. For instance, "block/cube_all" is turned into "minecraft:block/cube_all". Then, this String is converted into a path as follows:

"minecraft:block/cube_all"

-> "assets/minecraft/models/block/cube_all.json"


So, if you want to extend a model file in your own mod's assets, you need to write your modid followed by a colon in front of the file name: "tutorial:block/tutorial_block".



The paths in the"texture" tag are resolved like this:

First, if the String does not contain a ':', the String "minecraft:" is used as a prefix. For instance, "blocks/dirt" is turned into "minecraft:dirt". Then, this String is converted into a path as follows:

"minecraft:blocks/dirt"

-> "assets/minecraft/textures/blocks/dirt.png"


So, if you want to use a texture from your own mod's assets, you need to write your modid followed by a colon in front of the file name: "tutorial:blocks/tutorial_block".



Note that model files are located in "models/block" or "models/item" while the textures are in "textures/blocks" or "textures/items".

Model files: defining a new block model

When you want to define a new block model, you need to create a new json file. The best way to keep your coding clean is to store your custom models in a different folder than your block specific model files (The ones with a parent tag).

I usually use the folder "assets/<modid>/models/model" for my own models.

As an example, I'll cover the vanilla model "stairs.json"

models/block/stairs.json:
{
    "textures": {
        "particle": "#side"
    },
    "elements": [
        {   "from": [ 0, 0, 0 ],
            "to": [ 16, 8, 16 ],
            "faces": {
                "down":  { "uv": [ 0, 0, 16, 16 ], "texture": "#bottom", "cullface": "down" },
                "up":    { "uv": [ 0, 0, 16, 16 ], "texture": "#top" },
                "north": { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "north" },
                "south": { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "south" },
                "west":  { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "west" },
                "east":  { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "east" }
            }
        },
        {   "from": [ 8, 8, 0 ],
            "to": [ 16, 16, 16 ],
            "faces": {
                "down":  { "uv": [ 8, 0, 16, 16 ], "texture": "#bottom", "cullface": "down" },
                "up":    { "uv": [ 8, 0, 16, 16 ], "texture": "#top", "cullface": "up" },
                "north": { "uv": [ 0, 0,  8,  8 ], "texture": "#side", "cullface": "north" },
                "south": { "uv": [ 8, 0, 16,  8 ], "texture": "#side", "cullface": "south" },
                "west":  { "uv": [ 0, 0, 16,  8 ], "texture": "#side" },
                "east":  { "uv": [ 0, 0, 16,  8 ], "texture": "#side", "cullface": "east" }
            }
        }
    ]
}

Although this file is relatively large, it's quite easy to understand.

In the first line, the textures are assigned. But here, only the particle texture gets a new value, because this file is meant to be a parent file.

The assignment of the particle texture is pretty weird anyway: The assigned value starts with a '#'. This means, that the particle texture gets a new alias, namely side. Once the "side" texture is set, the particle texture is set with it. This is done here, so that everyone using this model does not have to worry about setting the particle texture (which must be set for every block) because it's done automatically.


In the next part of the file, the "elements" tag contains the defined cuboids that a necessary to make a stair block. The block consists out of a half block at the bottom (like a half slab) and a quarter of a block, placed right above the half slab.


The definition of the half slab looks like this:

models/block/stairs.json:
{
    [...]
    "elements": [
        {   "from": [ 0, 0, 0 ],
            "to": [ 16, 8, 16 ],
            "faces": {
                "down":  { "uv": [ 0, 0, 16, 16 ], "texture": "#bottom", "cullface": "down" },
                "up":    { "uv": [ 0, 0, 16, 16 ], "texture": "#top" },
                "north": { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "north" },
                "south": { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "south" },
                "west":  { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "west" },
                "east":  { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "east" }
            }
        },
        [...]
    ]
}

Here, we first have a definition of the size of this cuboid. This size is defined using two 3D-Vertices (passed as arrays of three double values). One defines the minimum point and the other one the maximum point. You need to be careful not to flip them around, because this would invert the faces of the cuboid.

The second important tag is the "faces" tag. This defines the texture and uv coordinates for the faces that should be rendered. In this case, every face is rendered, but this is not necessary every time. If a face should not be rendered, it's tag can be left out.

A face definition consists of the name of the face (up, down, north, south, east or west) and some data about the face itself. This contains it's texture, the uv coordinates and optionally the cullface tag, a rotation tag and a tint tag.

The texture is defined using the '#' as we saw above. To apply a real texture to it, the texture's name must be mapped within the "texture" tag.The uv coordinates are used to define the position of the texture's extract that the face should contain. If the full texture should be used, this value is "[0, 0, 16, 16]".

The uv coordinates are written in the following order: [uMin, vMin, uMax, vMax], where u is the x coordinate on the image and v the y coordinate on the image. Both reach from 0 to 16. The uv coordinate point 0|0 is the top-left corner of the image. With this information, our stairs block can already be rendered.

But, we also have some additional information here: the cullface.

This is used to make the rendering of the blocks faster. When a textured face aligns with the block's bounds it should get a cullface tag. When a block is placed at the north side of our block and a texture has the tag "cullface: north", it will not be rendered and thus it saves resources and makes the rendering faster.


Basically, these tags are enough to define a variety of blocks, but there are some other tags as well that can be added to the file:

  • "ambientocclusion": false/true (placed in the main tag)
    This tag defines, whether the position and lighting of nearby blocks should be used to calculate this block's lighting. If this tag is missing, it defaults to true.
  • "rotation": {...} (placed in a tag in "elements")
    This tag defines the rotation of the element around a given axis. Look at the full example below to see the tags used for the rotation.
  • "shade": false/true (placed in a tag in "elements")
    This tag turns of the shade casted by this cuboid if set to false. Default is true.
  • "rotation": 0/90/180/270 (placed in a face tag)
    This tag defines the rotation of the texture in 90 degree steps. The default is 0. Note that the rotation is done after the uv coordinates are applied.
  • "tintindex": 0,1,... (placed in a face tag)
    If this tag exists, the face is colored using the colorMultiplier defined for this block. This is used for grass and leaves for instance. It only has an effect if the block has a color multiplier defined.
  • "__comment": "a comment" (placed anywhere)
    A comment tag can be placed anywhere in the file (if the JSON rules allow it). It is used to add a comment to certain settings. Basically, the name is free to choose but it musn't be one of the names with a special meaning.

The following is an example of a model file with every possible tag applied: (This does not claim to be useful at all)

Example:
{
    "textures": {
        "particle": "#side"
    },
    "ambientocclusion": false,
    "elements": [
        {   "__comment": "The one and only cuboid of this model",
            "from": [ 0, 0, 0 ],
            "to": [ 16, 8, 16 ],
            "shade": false,
            "rotation": {
                "origin": [8, 8, 8],
                "axis":"y",
                "angle":45,
                "__comment":"The angle must be between -45 and 45 and can be varied in 25.5 degree steps"
            }
            "faces": {
                "__comment": "If the block had a colorMultiplier, the top face would be tinted",
                "down":  { "uv": [ 0, 0, 16, 16 ], "texture": "#bottom", "cullface": "down", "rotation": 180 },
                "up":    { "uv": [ 0, 0, 16, 16 ], "texture": "#top", "tintindex": 0 },
                "north": { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "north" },
                "south": { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "south" },
                "west":  { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "west" },
                "east":  { "uv": [ 0, 8, 16, 16 ], "texture": "#side", "cullface": "east" }
            }
        }
    ]
}

Model Files: Item Models

There are two common ways of creating an Item model: The first one is by using a block model and applying special transformations to it. The other one is by using the builtin item models, which results in the typical item look as a solidified 2D texture.

If you want to use the builtin item renderer, you need to set the parent of the model to "builtin/generated" and the texture "layer0" to your item's texture. This applies the default item renderer to your item. There are some other builtin values that are used for some special blocks and items in vanilla:

  • builtin/entity: Uses the hardcoded TileEntityRenderer. Used by Chest, Enderchest, Skull and Banner
  • builtin/compass: Used to define the correct animation frame for the compass rendering.
  • builtin/clock: Used to define the correct animation frame for the clock rendering.

These special builtin renderers are useless for most modded blocks and items.


If you want to render an Item like a block, you need to define the block model as the parent ("modid:block/modelname").


To render the item properly, some transformations are necessary. These have to be written in the "display" tag of the item's model. The display tag has four subtags, which are used to define special transformations for different rendering modes. The subtags are: "thirdperson", "firstperson", "gui" and "head". Each of them defines a mode in which the item can be rendered:

  • thirdperson: A player watched by another one is holding the item in his hand.
  • firstperson: A player sees the item from his view when he holds it.
  • gui: The item is rendered in the inventory slots
  • head: A player wears this item on his head (currently only used by banners)

The last possibility of an item being rendered is as a tossed item or inside an item frame. There, no transformation is applied.


The transformations inside the display tags consist of three tags: rotation, translation and scale. The values are given as an array of three double values and default to [0, 0, 0], or [1, 1, 1] for the scale tag. These transformations can mostly be copied from a vanilla item, but if special transformations are needed, I can recommend the Item transform helper mod. It can be found at planetminecraft.com.


In the following, I've collected a few default transformation values for different items and blocks:

Standard Item (redstone.json):
{
    "parent": "builtin/generated",
    "textures": {
        "layer0": "items/redstone_dust"
    },
    "display": {
        "thirdperson": {
            "rotation": [ -90, 0, 0 ],
            "translation": [ 0, 1, -3 ],
            "scale": [ 0.55, 0.55, 0.55 ]
        },
        "firstperson": {
            "rotation": [ 0, -135, 25 ],
            "translation": [ 0, 4, 2 ],
            "scale": [ 1.7, 1.7, 1.7 ]
        }
    }
}

Standard Block (dirt.json):
{
    "parent": "block/dirt",
    "display": {
        "thirdperson": {
            "rotation": [ 10, -45, 170 ],
            "translation": [ 0, 1.5, -2.75 ],
            "scale": [ 0.375, 0.375, 0.375 ]
        }
    }
}
Special Block (banner.json):
{
    "parent": "builtin/entity",
    "display": {
        "thirdperson": {
            "rotation": [ 0, 90, -90 ],
            "translation": [ 0, 0, -4 ],
            "scale": [ 0.5, 0.5, 0.5 ]
        },
        "firstperson": {
            "rotation": [ 0, 225, 0 ]
        },
        "gui": {
            "rotation": [ 0, -65, 0 ],
            "translation": [ 0, -3, 0 ],
            "scale": [ 0.85, 0.85, 0.85 ]
        },
        "head": {
            "translation": [ 0, 8, 3.5 ],
            "scale": [ 1.5, 1.5, 1.5 ]
        }
    }
}
Swords (iron_sword.json):
{
    "parent": "builtin/generated",
    "textures": {
        "layer0": "items/iron_sword"
    },
    "display": {
        "thirdperson": {
            "rotation": [ 0, 90, -35 ],
            "translation": [ 0, 1.25, -3.5 ],
            "scale": [ 0.85, 0.85, 0.85 ]
        },
        "firstperson": {
            "rotation": [ 0, -135, 25 ],
            "translation": [ 0, 4, 2 ],
            "scale": [ 1.7, 1.7, 1.7 ]
        }
    }
}
Pickaxes (iron_pickaxe.json):
{
    "parent": "builtin/generated",
    "textures": {
        "layer0": "items/iron_pickaxe"
    },
    "display": {
        "thirdperson": {
            "rotation": [ 0, 90, -35 ],
            "translation": [ 0, 1.25, -3.5 ],
            "scale": [ 0.85, 0.85, 0.85 ]
        },
        "firstperson": {
            "rotation": [ 0, -135, 25 ],
            "translation": [ 0, 4, 2 ],
            "scale": [ 1.7, 1.7, 1.7 ]
        }
    }
}

Bows (bow.json):
{
    "parent":"tutorial:block/tutorial_block",
    "display": {
        "thirdperson": {
            "rotation": [ 10, -45, 170 ],
            "translation": [ 0, 1.5, -2.75 ],
            "scale": [ 0.375, 0.375, 0.375 ]
        }
    }
}

Recommended tutorials to continue with

Take a look at the tutorial overview and decide what you want to do next!


Comments and Questions:

If you want to report modding problems, please make sure to include the code in a pastebin link or something else! Don't just write "It doesn't work", otherwise your post will be deleted. For more complicated problems, please use the troubleshooter form.