リソースパック小ネタ：モデルの継承 ～親から子へ～

この記事は３０分程度で読めます。

# はじめに
前々回の[記事](https://qiita.com/johniki/items/f51dcab49d0a2e1a6b45)でリソパの小ネタの１つとしてモデルの「カリング」について書きました。今回は小ネタの継承について書きます。
IT用語でいう「継承」というのは、新しく物を作る時に参考元からある特徴を引き継いで再利用すること、を指します。人で言うところの「足が長いところが父から遺伝したね」みたいなことです。この記事では参考にする３Dモデルを「親モデル」、参考にして新しく作るモデルを「子モデル」と呼ぶことにします。

# なぜリソパで継承を使うのか
リソパのサイズを小さくしたり、効率よく作るためです。例えば、マインクラフトには立方体（cube）の形をしたアイテムが大量にありますが、この３Dモデルを１つ１つ BlockBench などのエディタで作っていたら大変です。縦x横x高さのサイズをマウスでカチカチクリックして、テクスチャを貼って、インベントリでの見た目を決めて、左手に持った時や頭に装着した場合の大きさを決めて、なんてことをしていたら１つのモデルを作成するために 10 分以上かかるかも知れません。
継承を使えば、３Dモデリングの知識が全くない人が「新しいテクスチャのアイテム追加したいな」などと思えばささっと追加することもできます。「私の作ったアイテムは高さが８なのに、あなたの作ったアイテムは何故高さが１６なの？ちゃんと揃えなさいよ！」みたいな面倒事も無くなります。
共通の情報を使いまわすことによって後から修正する箇所を少なくすることができます。親モデルの形状を変えれば作った全ての子モデルの形状を自動で変えることができます。そのために継承を使います。立方体の形を親モデルから継承して、子モデルはテクスチャだけを変えれば完成です。

例えば、エディターとして BlockBench を使う場合には、プロジェクトの新規作成時に親モデルを指定することができます（使わない場合は空欄）。ここでは「test_parent」という親モデルを使っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/0025a27e-5a4e-ab67-d694-ffef845063ff.png)

なお、BlockBench のバージョンによっては「親モデル」ではなく「ファイル名」と書かれており用途がいまいち分かりにくいです。4.5以降のバージョンから正式に親モデルを読み込めるようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/5a10f699-98a2-8b4a-3e7e-5dceb58da285.png)

# 実際にやってみる
例として「親モデルでアイテムの形状を指定し、子モデルでは形状を作らずにテクスチャのみを指定する」という主旨で作ってみます。親から形状を継承する、ということです。なお、BlockBench ではまだ完全には親子の継承に対応できてない（たぶん）ようなので、部分的にテキストエディタを使う必要があります（たぶん）。
まず親モデルを作ります。自分のプロジェクト名が「test_parent」、親の親は今のところ無いので空欄。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/cc36572b-0f29-3184-7141-2b5bba3cb03a.png)

適当に cube を置いて作りたいモデルのテクスチャを仮で貼ります。親モデルにはテクスチャを指定しないという主旨なのであとで剥がします。とりあえず２種類のテクスチャをペタペタ貼った立方体のアイテムを作りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/54e5369a-4162-52b2-5e4a-dd17a993f276.png)

読み込んだテクスチャのプロパティから「変数」「フォルダ」「ネームスペース」などを変えることができるので、自分の環境にあわせて変えてください。私は１つ目のテクスチャを texture1、２つ目のテクスチャを texture2 と名付けました。デフォルトだと名前が１とか適当な感じになってます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/26451dd5-9ff0-e57e-5b98-3c9f935c5449.png)

これを json に書き出すと次のようなモデルができます。ho.png と ge.png という超適当な２つのテクスチャを読み込んで６面体に貼ったアイテムです。"textures" の欄を見ると、ho.png には先ほど BlockBench の「変数」の箇所に入力した texture1 という名前が付いており、ge.png には texture2 という名前が付いています。そして、モデルの各面 "faces" にはテクスチャとして texture1 と texture2 を使う、と書かれています（#を付けて変数を参照しています）。

``` test_parent.json
{
  "textures": {
    "particle": "hoge:item/ho",
    "texture1": "hoge:item/ho",
    "texture2": "hoge:item/ge"
  },
  "elements": [
    {
      "from": [4, 4, 4],
      "to": [12, 12, 12],
      "faces": {
        "north": {"uv": [0, 0, 16, 16], "texture": "#texture1"},
        "east": {"uv": [0, 0, 16, 16], "texture": "#texture1"},
        "south": {"uv": [0, 0, 16, 16], "texture": "#texture2"},
        "west": {"uv": [0, 0, 16, 16], "texture": "#texture2"},
        "up": {"uv": [0, 0, 16, 16], "texture": "#texture1"},
        "down": {"uv": [0, 0, 16, 16], "texture": "#texture2"}
      }
    }
  ]
}
```

ここでおもむろに、"textures"の中の ho.png と ge.png の定義をテキストエディタで消して次のように書き換えて下さい。particle は適当に north の面と同じテクスチャ #texture1 を使うことにしましょう。

``` test_parent.json
{
  "textures": {
    "particle": "#texture1"
  },
  "elements": [
    {
      "from": [4, 4, 4],
      "to": [12, 12, 12],
      "faces": {
        "north": {"uv": [0, 0, 16, 16], "texture": "#texture1"},
        "east": {"uv": [0, 0, 16, 16], "texture": "#texture1"},
        "south": {"uv": [0, 0, 16, 16], "texture": "#texture2"},
        "west": {"uv": [0, 0, 16, 16], "texture": "#texture2"},
        "up": {"uv": [0, 0, 16, 16], "texture": "#texture1"},
        "down": {"uv": [0, 0, 16, 16], "texture": "#texture2"}
      }
    }
  ]
}
```

これで親モデルは完成です。一度普通にモデルを作ってテキストエディタでテクスチャの名前を消しただけです。
続いて、子モデルを作ります。冒頭の通り、先ほど作った親モデルの名前を書きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/85f18fc2-d94a-109c-8a8c-6bd11b8c5b73.png)

子モデルは形状は不要という主旨なのでモデリングはしません。テクスチャだけさっきと同じように読み込みましょう。変数名は先ほどと同じ名前を付けます（子で付けた名前を親の方では # で始まる名前で参照して使うことができます）。

![parent03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/c538b191-1401-25b0-dad2-fdf53ec72145.png)

子モデルはこれで完成です。json に書き出すと次のようなシンプルなモデルになります。
「ほ」と「げ」を読み込んだアイテムです。

``` test1.json
{
  "parent": "hoge:item/test_parent",
  "textures": {
    "texture1": "hoge:item/ho",
    "texture2": "hoge:item/ge"
  }
}
```

同じ手順でいくつか適当に子モデルを作ってみます。
テクスチャを２つとも「げ」にしたアイテムです。

``` test2.json
{
  "parent": "hoge:item/test_parent",
  "textures": {
    "texture1": "hoge:item/ge",
    "texture2": "hoge:item/ge"
  }
}
```

マイクラデフォルトのアイテムであるダイアモンドとゴールドのテクスチャを使ってみました。

``` test3.json
{
  "parent": "hoge:item/test_parent",
  "textures": {
    "texture1": "block/diamond_block",
    "texture2": "block/gold_block"
  }
}
```

続いて、作った３つのモデルをマイクラ内で使えるようにします。継承とは関係ないので説明は省略します。

``` paper.json
{
  "parent": "minecraft:item/generated",
  "textures": {
    "layer0": "minecraft:item/paper"
  },
  "overrides": [
    {
      "predicate": {
        "custom_model_data": 1
      },
      "model": "hoge:item/test1"
    },
    {
      "predicate": {
        "custom_model_data": 2
      },
      "model": "hoge:item/test2"
    },
    {
      "predicate": {
        "custom_model_data": 3
      },
      "model": "hoge:item/test3"
    }
  ]
}
```

こんな感じになりました。

![parent01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/316b7840-dd34-7000-b9e9-8bfc527eac53.png)

なお、継承できる情報は他にもいろいろあります。例えば、右手に持つと大きさ２倍、左手に持つと見えなくなるようにディスプレイを設定した情報を継承することもできます。ちなみに継承は１代ではなく、親の親や親の親の親なども作ることができます。
先祖のモデルでディスプレイ設定を上記の通りに書くとこうなります。

``` test_ancestor.json
{
  "gui_light": "front",
  "display": {
    "thirdperson_righthand": {
      "scale": [2, 2, 2]
    },
    "thirdperson_lefthand": {
      "scale": [0, 0, 0]
    }
  }
}
```

そしてそれを先ほどの親モデルの親に指定します（"parent" の記載を追加しました）。

``` test_parent.json
{
  "parent": "hoge:item/test_ancestor",
  "textures": {
    "particle": "#texture1"
  },
  "elements": [
    {
      "from": [4, 4, 4],
      "to": [12, 12, 12],
      "faces": {
        "north": {"uv": [0, 0, 16, 16], "texture": "#texture1"},
        "east": {"uv": [0, 0, 16, 16], "texture": "#texture1"},
        "south": {"uv": [0, 0, 16, 16], "texture": "#texture2"},
        "west": {"uv": [0, 0, 16, 16], "texture": "#texture2"},
        "up": {"uv": [0, 0, 16, 16], "texture": "#texture1"},
        "down": {"uv": [0, 0, 16, 16], "texture": "#texture2"}
      }
    }
  ]
}
```

こうなります。基本的な使い方としてはモデル形状がまったく同じものを量産したいときに継承を使います。

![parent02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/0bc10830-2556-585b-17a9-670b2f93fa1a.png)

# まとめ
子供全員の身長が高いときは、親の身長がそもそも高かったんじゃね？ってことです。