データ方式による立方体の作成 -- PythonによるBlender 3DCGモデリング(5) --

2015/06/05
  • このエントリーをはてなブックマークに追加
前回はPythonスクリプトからBlenderに追加したオブジェクトの形状をSimple Deform モデファイアで変形し、それを3Dプリントしました。今回はプリミティブ方式以外のオブジェクト作成方法について紹介したいと思います。

本連載で使用しているサンプルコードは、githubにて公開しています。
なお本記事のソースコードは、下記の環境で動作確認をしています。
Mac: OS X Yosemite (Vesion 10.10.3)
Windows: Windows 8.1
Blender: 2.74
Python: 3.4.2 (Blenderにバンドルされてるpythonです)

1. オブジェクトの追加方法

第2回で紹介したように、 スクリプトを使ってオブジェクトを作成するには、主に以下の4つの方法があります。
  1. 1. プリミティブ方式
  2. 2. データ方式
  3. 3. オペレータ方式
  4. 4. 外部データのインポート
第2回から第4回までは、「1. プリミティブ方式」によりオブジェクトを作成しました。 今回は他のオブジェクト作成方法である、「2. データ方式」についてご紹介したいと思います。

2. データ方式によるオブジェクトの追加

データ方式によるデータの追加する場合には、下記の操作が必要です。

  1. 2.1 データオブジェクトの作成
  2. 2.2 データオブジェクトをシーンに追加
  3. 2.3 データオブジェクトに形状データをアタッチ

2.1 データオブジェクトの作成

「2.1 データオブジェクトの作成」は、下記のようなコードです。

mesh = bpy.data.meshes.new('CubeMeshByData')
obj = bpy.data.objects.new('CubeObjectByData', mesh)
Meshオブジェクトを作成して、そのMeshを元にObjectデータ(bpy.types.Objectのインスタンス)を作成します。 newメソッドの引数にmeshを渡すことで、bpy.types.Objectのdataプロパティにmeshが代入されます。

2.2 データオブジェクトをシーンに追加

次に「2.2 データオブジェクトをシーンに追加」は、下記のようなコードです。
bpy.context.scene.objects.link(obj)
このメソッドは、オブジェクトをシーンにリンクします(そのままですが…)。
逆にシーンからオブジェクトを削除する場合にはbpy.contest.scene.objects.unlinkメソッドを使用します。

2.3 データオブジェクトに形状データをアタッチ

これをお読みの方はすでにお気づきかと思いますが、まだ作成したいオブジェクトの形状を指定していません。 それを行うのが「2.3 データオブジェクトに形状データをアタッチ」です。今回は、例としてBlenderを起動した時に表示される立方体を作成してみます。

startup.blendでカスタマイズしていない場合、Blenderを起動した時に立方体が表示されます。この立方体は、原点を中心とする、辺の長さが2の立方体です。
これのことです

この立方体の座標は下図のようになっています。

デフォルトで表示される立方体の座標

この座標を格納するリストをPythonで作成してみましょう。

vertices = [(x, y, z) for x in [-1, 1] for y in [-1, 1] for z in [-1, 1]]
これを「2.1 データオブジェクトの作成」で作成したmeshデータに与えてあげれば、頂点データを作成することが出来ます。これは下記のコードで行います。
mesh.from_pydata(vertices, [], [])
mesh.update()
ここまでをまとめると下記のようなメソッドができます。
def add_cube_by_data():
    mesh = bpy.data.meshes.new('CubeMeshByData')
    obj = bpy.data.objects.new('CubeObjectByData', mesh)
    bpy.context.scene.objects.link(obj)

    vertices = [(x, y, z) for x in [-1, 1] for y in [-1, 1] for z in [-1, 1]]

    mesh.from_pydata(vertices, [], [])
    mesh.update()
下記のようにメソッドを呼び出す記述を追加して、実行してみます。
if __name__ == "__main__":
    delete_all()
    add_cube_by_operator()
コマンドライン(Mac:ターミナル、Windows:コマンドプロンプト)でコードがある場所へ移動し、下記をタイプします。
$ blender -P tut5.py
実行結果。定義した点しか表示されない。

点しか表示されませんね…。これは、点の定義のみmeshデータに与えているためです。では、面のデータを与えてみましょう。 …ところで面のデータってなんでしょうか?

立方体は、6つの正方形で構成されます。それぞれの正方形は4つの頂点を持ちます。 そのため、面のデータとは、面を構成する頂点を定義するものとなります。

もう少し具体的に見てみましょう。下図のように立方体の頂点に生成される順番に番号を振ります。下図の右側が展開図です(色は分かりやすくなるようにつけています)

立方体の頂点と展開図
ここでは右手座標系で考えるため、面は反時計回りの頂点列によって定義されます。
面は反時計回りの頂点列によって定義される。
以上のことより、面を表す頂点列は下記の6つのセットになります。
(4, 5, 1, 0) (0, 1, 3, 2) (2, 3, 7, 6)
(6, 7, 5, 4) (3, 1, 5, 7) (0, 2, 6, 4)
この定義をソースコードに追加し、from_pydataメソッドの第3引数に渡してあげます。
ちなみに第2引数には、Edgeに関するデータを与えることが出来ます。
faces = [
    (4, 5, 1, 0),
    (0, 1, 3, 2),
    (2, 3, 7, 6),
    (6, 7, 5, 4),
    (3, 1, 5, 7),
    (0, 2, 6, 4)
]
mesh.from_pydata(vertices, [], faces)
もう一度実行してみましょう。
今度は面がちゃんと貼られた!

今回はちゃんと面を貼ることができました!

しかし、プリミティブ方式では1つのメソッドで立方体を作成することが出来たのに対して、 たった1つの立方体でも非常に面倒くさい手続きが必要となりました。 ではデータ方式のメリットはなんでしょうか?この点について、次回紹介したいと思います。


今回は、データ方式によって立方体を作成する方法について紹介しました。次回は、データ方式によるオブジェクトの作成が有効な場合についてご紹介したいと思います。
『こういうことが知りたい!』とかありましたら、私のtwitterアカウントにreplyいただければと思います。

ga.rd

Posts

【3Dフィギュア部】スキャンからフィギュアをつくってみた with ルーナちゃん


Blender Conference 2015に参加してきました!


「Autodesk Gallery Pop-Up Tokyo」にRinkakが出展中!


Maker Faire Tokyo 2015 ご来場ありがとうございました!


でこぼこMAPで遊ぼう ①メイキング・オブ・関ヶ原の合戦


more...