Blender×Python理解への道 ～第1章 モディファイアー。それは、Blenderの原点で頂点～

# 今回のテーマ (モディファイアー)
3DCGでのものづくりを効率化したいというのが本シリーズのテーマなわけですが、実はプログラミング抜きでも効率化を行うための仕組みがあるのです。

それが、モディファイアーと呼ばれた🔧(スパナ)マークのアイコンからアクセスできる機能です。

## モディファイアーの設定方法 (手動)

以下のようなメニューの中にある

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/540971ce-c951-ed80-e565-7c34daba41a1.png)

以下のアイコンですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/f55d4473-2be2-d6d0-ec76-3fa168ddf695.png)

モディファイアーにはたくさんの種類があって、
* 物体をもとに別の物体をくりぬいたり
* 物体を複数個ならべたり
と色んなことができます。

試しに、前回のコードから立方体を作成して、手動で角が丸まった立方体にしましょう。

``` Python
import bpy

# 立方体を追加
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0))

```
作成された立方体をクリックして、
先ほどのメニューのモディファイアーから「モディファイアーを追加をクリック」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/53e01eed-11ce-9735-dc4a-dedee210e18f.png)

「生成」 > 「ベベル」の順に辿ってクリックする。
(マウスが離れすぎるとメニューが消えちゃうので慎重気味に操作する必要あり。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/689e0afc-3588-1536-3fd6-d91a91e94130.png)


以下のような角が削られたような立方体に変わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/388e950a-ad67-ea86-ee6e-ff1f5e2088ab.png)

「セグメント」のオプションを変えることで、角の分割数を増やすことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/6b556ac9-6661-d53d-6de3-e92aec3f3683.png)

さらに、「量」のオプションを変えることで、どこから角をとるのかを調整できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/17a0d9e8-2205-e9ec-37e0-c10657064539.png)

ということで、色んなモディファイアーのPython実装を見てみましょう。


# Pythonによるモディファイアー設定

上記の角を取った立方体をPythonで再現すると以下のようになります。

``` Python
import bpy

# 立方体を追加
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0))

# 現在選択されているオブジェクトを取得
obj = bpy.context.active_object

# オブジェクトにベベルモディファイアを追加
bevel_modifier = obj.modifiers.new(name="ベベル", type='BEVEL')

# モディファイアのプロパティを設定
bevel_modifier.offset_type = 'OFFSET'	# 幅のタイプ
bevel_modifier.width = 0.8  # 量
bevel_modifier.segments = 3  # セグメント

```

ちなみに、画面(日本語)で「量」を設定するのは、
ソースコード(英語)だとどんな値が該当するの？というのは、
画面で実際に設定した後にスクリプト画面の左下に表示されるログを見れば分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/c3ae9818-6c8a-3fa2-a091-1376147aab6d.png)

bpy.context.object.modifiers["ベベル"].width = 0.5
の通りに、widthが画面上の「量」に当たりますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/ea3245f7-c376-324a-22b5-b464f08c7077.png)


# モディファイアの種類

obj.modifiers.newメソッドのtypeに渡す値と、その他の設定値を以下に整理してみました。
全部のモディファイアを知っているわけではないですが。

こんなに種類があったら、やりたいことが既にモディファイアとして存在する可能性もありますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/3c2f7733-bca9-b527-ccd3-077f21e18591.png)

上記のメニューをそれぞれ見てみましょう。

## 編集

一発目から、使ったことがない分類です……
今度詳しく見てみたいですが、今回は本筋からずれるので詳細は割愛。

| 名前 | type | クラス名 | ドキュメント |
|:-|:-|:-|:-:|
| データ転送 | DATA_TRANSFER | DataTransferModifier | [リンク](https://docs.blender.org/api/current/bpy.types.DataTransferModifier.html) |
| メッシュキャッシュ | MESH_CACHE | MeshCacheModifier | [リンク](https://docs.blender.org/api/current/bpy.types.MeshCacheModifier.html) |
| メッシュ連番キャッシュ | MESH_SEQUENCE_CACHE | MeshSequenceCacheModifier | [リンク](https://docs.blender.org/api/current/bpy.types.MeshSequenceCacheModifier.html) |
| UV投影 | UV_PROJECT | UvProjectModifier | [リンク](https://docs.blender.org/api/current/bpy.types.UvProjectModifier.html) |
| UVワープ | UV_WARP | UvWarpModifier | [リンク](https://docs.blender.org/api/current/bpy.types.UvWarpModifier.html) |
| 頂点ウェイト編集 | VERTEX_WEIGHT_EDIT | VertexWeightEditModifier | [リンク](https://docs.blender.org/api/current/bpy.types.VertexWeightEditModifier.html) |
| 頂点ウェイト合成 | VERTEX_WEIGHT_MIX | VertexWeightMixModifier | [リンク](https://docs.blender.org/api/current/bpy.types.VertexWeightMixModifier.html) |
| 頂点ウェイト(近傍) | VERTEX_WEIGHT_PROXIMITY | VertexWeightProximityModifier | [リンク](https://docs.blender.org/api/current/bpy.types.VertexWeightProximityModifier.html) |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/4cef091c-b89b-2563-98d9-4edfea29c88c.png)


## 生成

逆に一番使う種別ですね。
ミラー・サブディヴィジョンサーフェスなどに関しては、どのBlender本にも書いているのでは？と思います。

| 名前 | type | クラス名 | ドキュメント |
|:-|:-|:-|:-:|
| 配列 | ARRAY | ArrayModifier | [リンク](https://docs.blender.org/api/current/bpy.types.ArrayModifier.html) |
| ベベル | BEVEL | BevelModifier | [リンク](https://docs.blender.org/api/current/bpy.types.BevelModifier.html) |
| ブーリアン | BOOLEAN | BooleanModifier | [リンク](https://docs.blender.org/api/current/bpy.types.BooleanModifier.html) |
| ビルド | BUILD | BuildModifier | [リンク](https://docs.blender.org/api/current/bpy.types.BuildModifier.html) |
| デシメート | DECIMATE | DecimateModifier | [リンク](https://docs.blender.org/api/current/bpy.types.DecimateModifier.html) |
| 辺分離 | EDGE_SPLIT | EdgeSplitModifier | [リンク](https://docs.blender.org/api/current/bpy.types.EdgeSplitModifier.html) |
| マスク | MASK | MaskModifier | [リンク](https://docs.blender.org/api/current/bpy.types.MaskModifier.html) |
| ミラー | MIRROR | MirrorModifier | [リンク](https://docs.blender.org/api/current/bpy.types.MirrorModifier.html) |
| マルチレゾリューション | MULTIRES | MultiresModifier | [リンク](https://docs.blender.org/api/current/bpy.types.MultiresModifier.html) |
| リメッシュ | REMESH | RemeshModifier | [リンク](https://docs.blender.org/api/current/bpy.types.RemeshModifier.html) |
| スクリュー | SCREW | ScrewModifier | [リンク](https://docs.blender.org/api/current/bpy.types.ScrewModifier.html) |
| スキン | SKIN | SkinModifier | [リンク](https://docs.blender.org/api/current/bpy.types.SkinModifier.html) |
| ソリッド化 | SOLIDIFY | SolidifyModifier | [リンク](https://docs.blender.org/api/current/bpy.types.SolidifyModifier.html) |
| サブディヴィジョンサーフェス | SUBSURF | SubsurfModifier | [リンク](https://docs.blender.org/api/current/bpy.types.SubsurfModifier.html) |
| 三角面化 | TRIANGULATE | TriangulateModifier | [リンク](https://docs.blender.org/api/current/bpy.types.TriangulateModifier.html) |
| ボリュームのメッシュ化 | VOLUME_TO_MESH | VolumeToMeshModifier | [リンク](https://docs.blender.org/api/current/bpy.types.VolumeToMeshModifier.html) |
| 溶接 | WELD | WeldModifier | [リンク](https://docs.blender.org/api/current/bpy.types.WeldModifier.html) |
| ワイヤーフレーム | WIREFRAME | WireframeModifier | [リンク](https://docs.blender.org/api/current/bpy.types.WireframeModifier.html) |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/aee8382d-0313-1e60-6118-08dad52f9a60.png)


## 変形

実は未開拓ゾーンです。

| 名前 | type | クラス名 | ドキュメント |
|:-|:-|:-|:-:|
| アーマチュア | ARMATURE | ArmatureModifier | [リンク](https://docs.blender.org/api/current/bpy.types.ArmatureModifier.html) |
| キャスト | CAST | CastModifier | [リンク](https://docs.blender.org/api/current/bpy.types.CastModifier.html) |
| カーブ | CURVE | CurveModifier | [リンク](https://docs.blender.org/api/current/bpy.types.CurveModifier.html) |
| ディスプレイス | DISPLACE | DisplaceModifier | [リンク](https://docs.blender.org/api/current/bpy.types.DisplaceModifier.html) |
| フック | HOOK | HookModifier | [リンク](https://docs.blender.org/api/current/bpy.types.HookModifier.html) |
| ラブラシアン変形 | LAPLACIANDEFORM | LaplacianDeformModifier | [リンク](https://docs.blender.org/api/current/bpy.types.LaplacianDeformModifier.html) |
| ラティス | LATTICE | LatticeModifier | [リンク](https://docs.blender.org/api/current/bpy.types.LatticeModifier.html) |
| メッシュ変形 | MESH_DEFORM | MeshDeformModifier | [リンク](https://docs.blender.org/api/current/bpy.types.MeshDeformModifier.html) |
| シュリンクラップ | SHRINKWRAP | ShrinkwrapModifier | [リンク](https://docs.blender.org/api/current/bpy.types.ShrinkwrapModifier.html) |
| シンプル変形 | SIMPLE_DEFORM | SimpleDeformModifier | [リンク](https://docs.blender.org/api/current/bpy.types.SimpleDeformModifier.html) |
| スムーズ | SMOOTH | SmoothModifier | [リンク](https://docs.blender.org/api/current/bpy.types.SmoothModifier.html) |
| スムーズ(変形) | CORRECTIVE_SMOOTH | CorrectiveSmoothModifier | [リンク](https://docs.blender.org/api/current/bpy.types.CorrectiveSmoothModifier.html) |
| スムーズ(ラプラシアン) | LAPLACIANSMOOTH | LaplacianSmoothModifier | [リンク](https://docs.blender.org/api/current/bpy.types.LaplacianSmoothModifier.html) |
| サーフェス変形 | SURFACE_DEFORM | SurfaceDeformModifier | [リンク](https://docs.blender.org/api/current/bpy.types.SurfaceDeformModifier.html) |
| ワープ | WARP | WarpModifier | [リンク](https://docs.blender.org/api/current/bpy.types.WarpModifier.html) |
| 波 | WAVE | WaveModifier | [リンク](https://docs.blender.org/api/current/bpy.types.WaveModifier.html) |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/353ce30f-1795-a04c-9e3b-e6aeb8e5af3e.png)


## ノーマル

同じく未開拓ゾーンです。

| 名前 | type | クラス名 | ドキュメント |
|:-|:-|:-|:-:|
| 法線編集 | NORMAL_EDIT | NormalEditModifier | [リンク](https://docs.blender.org/api/current/bpy.types.NormalEditModifier.html) |
| 重み付き法線 | WEIGHTED_NORMAL | WeightedNormalModifier | [リンク](https://docs.blender.org/api/current/bpy.types.WeightedNormalModifier.html) |
| 角度でスムーズ | (未対応？) | (未対応？) | (未対応？) |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/a7fe9925-d03a-8986-e07a-4470990e0cb3.png)


## 物理演算

流体シミュレーションとかに使うモディファイアーですかね。
高性能なPCに買い換えたら試したい。

| 名前 | type | クラス名 | ドキュメント |
|:-|:-|:-|:-:|
| クロス | CLOTH | ClothModifier | [リンク](https://docs.blender.org/api/current/bpy.types.ClothModifier.html) |
| コリジョン | COLLISION | CollisionModifier | [リンク](https://docs.blender.org/api/current/bpy.types.CollisionModifier.html) |
| ダイナミックペイント | DYNAMIC_PAINT | DynamicPaintModifier | [リンク](https://docs.blender.org/api/current/bpy.types.DynamicPaintModifier.html) |
| 爆発 | EXPLODE | ExplodeModifier | [リンク](https://docs.blender.org/api/current/bpy.types.ExplodeModifier.html) |
| 流体 | FLUID | FluidModifier | [リンク](https://docs.blender.org/api/current/bpy.types.FluidModifier.html) |
| 海洋 | OCEAN | OceanModifier | [リンク](https://docs.blender.org/api/current/bpy.types.OceanModifier.html) |
| パーティクルインスタンス | PARTICLE_INSTANCE | ParticleInstanceModifier | [リンク](https://docs.blender.org/api/current/bpy.types.ParticleInstanceModifier.html) |
| パーティクルシステム | PARTICLE_SYSTEM | ParticleSystemModifier | [リンク](https://docs.blender.org/api/current/bpy.types.ParticleSystemModifier.html) |
| ソフトボディ | SOFT_BODY | SoftBodyModifier | [リンク](https://docs.blender.org/api/current/bpy.types.SoftBodyModifier.html) |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/96724574-9dee-fb34-095c-6a645ab14e05.png)


# 具体例

## ①物体を格子状に並べてみる
配列(Array)モディファイアーを使って、モンキー(スザンヌ)を並べる例です。
``` Python
import bpy

# モンキー(スザンヌ)
bpy.ops.mesh.primitive_monkey_add(
    location=(0, 0, 0), 
    scale=(1, 1, 1), 
)

# 現在選択されているオブジェクトを取得
obj = bpy.context.active_object

# オブジェクトに配列(Array)モディファイアを追加
row_array_modifier = obj.modifiers.new(
    name='行', 
    type='ARRAY', 
)

## 配列の数を3にする
row_array_modifier.count = 3

# オブジェクトに配列(Array)モディファイアを追加
column_array_modifier = obj.modifiers.new(
    name='列', 
    type='ARRAY', 
)

## オフセット(倍率) 係数Xを0にする
column_array_modifier.relative_offset_displace[0] = 0
## オフセット(倍率) 係数Yを2にする
column_array_modifier.relative_offset_displace[1] = 2
## 配列の数を2にする
column_array_modifier.count = 2
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/ae533571-a214-b4dd-b40b-74240ba91ea6.png)


## ②物体を他の物体でくり抜く

2つの立方体を用意して、メイン立方体をサブ立方体でくり抜く例です。

``` Python
import bpy

# 立方体を追加
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0))
cube_main = bpy.context.object
bpy.ops.mesh.primitive_cube_add(location=(0.5, 0.5, 0.5))
cube_sub = bpy.context.object

# オブジェクトにブーリアン(Boolean)モディファイアを追加
modifier = cube_main.modifiers.new(
    name='ブーリアン', 
    type='BOOLEAN', 
)

modifier.operation = 'DIFFERENCE'	# 差分
modifier.operand_type = 'OBJECT'	# 演算対象: オブジェクト
modifier.object = cube_sub	# オブジェクト
modifier.solver = 'EXACT'	# 正確

# メインオブジェクトを変更
bpy.context.view_layer.objects.active = cube_main

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/8c2e84a0-4db8-0f83-70c6-fb87d9d9f70a.png)

ちなみに、修正を反映するには∨マークから「適用」を選択するか、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978339/d3ae65f4-af75-2bad-0d86-8f09f6be19c2.png)

モディファイアーの変数に関して以下のようにmodifier_applyを実行することで、
モディファイアーをオブジェクトに永続的に反映できます。
``` Python
bpy.ops.object.modifier_apply(modifier=modifier.name)
```

:::note warn
一度モディファイアーを適応してしまうと、後から元の状態に戻せないので注意が必要です。