Skip to content

CTM Overrides in Models

ThePiGuy24 edited this page Mar 4, 2021 · 8 revisions

CTM data can be overridden in the model json when a texture is accessed, even if the texture does not have a ctm data compound in its metadata mcmeta file or even a mcmeta file at all. This page documents how it's done and an example of an application.

Adding ctm_overrides

Overrides to CTM data are targeted at faces with a specific tintindex id. These are marked in the model json in the elements as normal like would be normally done for trying to tint a face. These will work even regardless if the block does have tinting or not.

The improved Model structure is as follows, after the Vanilla Model json tags:

The root tag
├─ ...
├─ ctm_version : Set this to 1. Just version checking.
└─ ctm_overrides : A compound for a list of tint indexes to override ctm datas.
   └─ (a number corresponding to a tintindex) : new ctm data. (Essentially a copy of what'd you normally put in the texture mcmeta, minus the animation structure)
       ├─ proxy : A texture to use instead of this one. Used for resourcepacks/mods that want to use an entirely different texture when CTM is present. 
       │	      If this is defined, nothing else (aside from ctm_version) can be defined.
       ├─ type : Sets the render type. See below for a list of possible render types.
       ├─ layer : Sets rendering layer for texture. Can be: SOLID, CUTOUT, CUTOUT_MIPPED, or TRANSLUCENT.
       ├─ texture : A texture location to use instead of the texture in the element. Like proxy, but only for the texture itself and not associated metadata.
       ├─ textures : This is for extra textures needed by the render type. 
       │  └─ An array of extra textures used.
       └─ extra : Used for any additional information the render, or specific render type, may require.

Examples

"Giant" block of Cobblestone

The Twilight Forest had these blocks that were giant and took up 4 blocks cubed of space. Something similar in terms of block texture can be accomplished as seen below:


Click here to expand cobblestone.json

{
  "parent": "block/block",
  "textures": {
    "particle": "#all",
    "all": "blocks/cobblestone"
  },
  "elements": [{
    "from": [ 0, 0, 0 ],
    "to": [ 16, 16, 16 ],
    "faces": {
      "down":  { "texture": "#all", "tintindex": 0, "cullface": "down"  },
      "up":    { "texture": "#all", "tintindex": 0, "cullface": "up"    },
      "north": { "texture": "#all", "tintindex": 0, "cullface": "north" },
      "south": { "texture": "#all", "tintindex": 0, "cullface": "south" },
      "west":  { "texture": "#all", "tintindex": 0, "cullface": "west"  },
      "east":  { "texture": "#all", "tintindex": 0, "cullface": "east"  }
    }
  }],
  "ctm_version": 1,
  "ctm_overrides": {
    "0": {
      "type": "pattern",
      "extra": {
        "size": 4
      }
    }
  }
}

The benefits of this method instead of directly putting the mcmeta on the cobblestone.png file itself is that the only specifically the Cobblestone block will be receiving this effect. Other blocks that use this texture like the Lever will not.

Double Stone Slabs


Click here to expand double_stone.json

{
    "parent": "block/block",
    "textures": {
        "end": "blocks/stone_slab_top",
        "side": "blocks/stone_slab_side",
        "particle": "blocks/stone_slab_top"
    },
    "elements": [{
            "from": [ 0, 0, 0 ],
            "to": [ 16, 8, 16 ],
            "faces": {
                "down":  { "texture": "#end" , "cullface": "down" , "tintindex": 2 },
                "north": { "texture": "#side", "cullface": "north", "tintindex": 0 },
                "south": { "texture": "#side", "cullface": "south", "tintindex": 0 },
                "west":  { "texture": "#side", "cullface": "west" , "tintindex": 0 },
                "east":  { "texture": "#side", "cullface": "east" , "tintindex": 0 }
            }
        }, {
            "from": [ 0, 8, 0 ],
            "to": [ 16, 16, 16 ],
            "faces": {
                "up":    { "texture": "#end" , "cullface": "up"   , "tintindex": 3 },
                "north": { "texture": "#side", "cullface": "north", "tintindex": 1 },
                "south": { "texture": "#side", "cullface": "south", "tintindex": 1 },
                "west":  { "texture": "#side", "cullface": "west" , "tintindex": 1 },
                "east":  { "texture": "#side", "cullface": "east" , "tintindex": 1 }
            }
        }
    ],
    "ctm_version": 1,
    "ctm_overrides": {
        "0": {
            "type": "ctm",
            "textures": [ "blocks/stone_slab_side_ctm" ],
            "extra": {
                "connect_to": [
                    {
                        "block": "double_stone_slab",
                        "predicate": [
                            {"variant": "stone" },
                            { "seamless": false }
                        ]
                    }, {
                        "block": "stone_slab",
                        "predicate": [
                            { "variant": "stone" },
                            { "half": "bottom" }
                        ]
                    }
                ]
            }
        },
        "1": {
            "type": "ctm",
            "textures": [ "blocks/stone_slab_side_ctm" ],
            "extra": {
                "connect_to": [
                    {
                        "block": "double_stone_slab",
                        "predicate": [
                            {"variant": "stone" },
                            { "seamless": false }
                        ]
                    }, {
                        "block": "stone_slab",
                        "predicate": [
                            { "variant": "stone" },
                            { "half": "top" }
                        ]
                    }
                ]
            }
        },
        "2": {
            "type": "ctm",
            "textures": [ "blocks/stone_slab_side_ctm" ],
            "extra": {
                "connect_to": [
                    {
                        "block": "double_stone_slab",
                        "predicate": [
                            {"variant": "stone" },
                            { "seamless": false }
                        ]
                    }, {
                        "block": "stone_slab",
                        "predicate": [
                            { "variant": "stone" },
                            { "half": "bottom" }
                        ]
                    }
                ]
            }
        },
        "3": {
            "type": "ctm",
            "textures": [ "blocks/stone_slab_side_ctm" ],
            "extra": {
                "connect_to": [
                    {
                        "block": "double_stone_slab",
                        "predicate": [
                            {"variant": "stone" },
                            { "seamless": false }
                        ]
                    }, {
                        "block": "stone_slab",
                        "predicate": [
                            { "variant": "stone" },
                            { "half": "top" }
                        ]
                    }
                ]
            }
        }
    }
}

Ok, that's a bit much to look at, right? The cleaner version is below:

Cleaned version of double_stone.json

{
    "parent": "block/block",
    "textures": {
        "end": "blocks/stone_slab_top",
        "side": "blocks/stone_slab_side",
        "particle": "blocks/stone_slab_top"
    },
    "elements": [{
        	"from": [ 0, 0, 0 ],
            "to": [ 16, 8, 16 ],
            "faces": {
                "down":  { "texture": "#end" , "cullface": "down" , "tintindex": 0 },
                "north": { "texture": "#side", "cullface": "north", "tintindex": 2 },
                "south": { "texture": "#side", "cullface": "south", "tintindex": 2 },
                "west":  { "texture": "#side", "cullface": "west" , "tintindex": 2 },
                "east":  { "texture": "#side", "cullface": "east" , "tintindex": 2 }
            }
        }, {
        	"from": [ 0, 8, 0 ],
            "to": [ 16, 16, 16 ],
            "faces": {
                "up":    { "texture": "#end" , "cullface": "up"   , "tintindex": 1 },
                "north": { "texture": "#side", "cullface": "north", "tintindex": 3 },
                "south": { "texture": "#side", "cullface": "south", "tintindex": 3 },
                "west":  { "texture": "#side", "cullface": "west" , "tintindex": 3 },
                "east":  { "texture": "#side", "cullface": "east" , "tintindex": 3 }
            }
        }
    ],
    "ctm_version": 1,
    "ctm_overrides": {
        "0": { "type": "ctm", "textures": [ "blocks/stone_slab_top_ctm"  ], "extra": { "connect_to": [
        	{ "block": "double_stone_slab", "predicate": [{ "variant": "stone" }, { "seamless": false   }]},
        	{ "block": "stone_slab"       , "predicate": [{ "variant": "stone" }, { "half":    "bottom" }]}
        ]}},
        "1": { "type": "ctm", "textures": [ "blocks/stone_slab_top_ctm"  ], "extra": { "connect_to": [
        	{ "block": "double_stone_slab", "predicate": [{ "variant": "stone" }, { "seamless": false   }]},
        	{ "block": "stone_slab"       , "predicate": [{ "variant": "stone" }, { "half":    "top"    }]}
        ]}},
        "2": { "type": "ctm", "textures": [ "blocks/stone_slab_side_ctm" ], "extra": { "connect_to": [
        	{ "block": "double_stone_slab", "predicate": [{ "variant": "stone" }, { "seamless": false   }]},
        	{ "block": "stone_slab"       , "predicate": [{ "variant": "stone" }, { "half":    "bottom" }]}
        ]}},
        "3": { "type": "ctm", "textures": [ "blocks/stone_slab_side_ctm" ], "extra": { "connect_to": [
        	{ "block": "double_stone_slab", "predicate": [{ "variant": "stone" }, { "seamless": false   }]},
        	{ "block": "stone_slab"       , "predicate": [{ "variant": "stone" }, { "half":    "top"    }]}
        ]}}
    }
}

Observe that the layout for the model is practically identical to the vanilla Double Stone Slabs model, except that there are two cuboids, one half-cube on top and other half-cube on bottom. They all use different tintindex ids as well. These are pointed at by the ids inside the ctm_overrides compound.

The specific override itself replaces the ctm data of the original texture target with the overriding data. There is no partial override, all of the old ctm data is wiped and replaced with the override.

These overrides contain the ctm rendertype include conditional connections, allowing them to not only connect to itself but also the neighboring respective half-slab.