【Blender】をPythonで試してみた2

はじめに

こんにちは、がんがんです。今回はBlenderの続きをやっていきます。
前回記事はこちらから

gangannikki.hatenadiary.jp

今回はPlaneの謎を解明していくために、Blender上のコンソールからいろいろ動かしていきます。

参考記事

オブジェクトの一覧を参考にする際に参考にしました。
Blender で Python スクリプトを実行してみる

実際にいろいろ作成するときはこちらを参考にしました。
blog.engineer.adways.net

躓いたことメモ

躓いたことを忘れないうちに箇条書きでメモしておきます。

1. テキストエディタを開くことができる

テキストエディタ下の+ボタン(画像中の丸で囲んだところ)を押すとテキストエディタにてコードを書くことができます。
コンソールだけでなくエディタも開けるのはとても便利です。


2. 日本語表示は注意が必要
日本語の方が理解しやすくて楽ということで日本語化していました。
しかし、これにより、bpy.data.objectsの格納がおかしくなってました。
試しに、板、カメラ、照明を配置したあとに中身を出力してみます。

>>> for i in bpy.data.objects:
...     print(i.name)
...     
カメラ
ポイント
平面

すると、日本語のまま格納されていました。
ランプがポイントになっているのはとりあえず放置
この日本語が原因で前回はエラーが出たのではないかなと思います。

実験

1. まずは板(Plane)をレンダリング

まずは一枚の板をレンダリングしてみます。
スクリプトの実行はテキストエディタにカーソル合わせてAlt + Pまたはコンソール->Text中にあるRun Scriptで実行。

import bpy

#  reset objects
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete(True)

#  plane add
bpy.ops.mesh.primitive_plane_add(location=(0,0,0))

とりあえず、しっかりと表示されています。
f:id:gangannikki:20181111171831j:plain

2. カメラ、照明を追加してみる

次にカメラや照明を追加していきます。なお、画像の保存先は各自のパスを指定ください。
参考記事ではC直下にtmpフォルダを作成しその中に保存しています。

import bpy
import math

#  reset objects
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete(True)

#  plane add
bpy.ops.mesh.primitive_plane_add(location=(0, 0, 0))

#  lamp add
bpy.ops.object.lamp_add(location=(0.0, 0.0, 2.0))

#  camera add
bpy.ops.object.camera_add(location=(5.0, 0.0, 5.0))
bpy.data.objects["Camera"].rotation_euler = (math.pi*1/4, 0, math.pi*1/2)

#  render
bpy.context.scene.render.resolution_x = 500
bpy.context.scene.render.resolution_y = 500
bpy.context.scene.render.resolution_percentage = 100
bpy.context.scene.camera = bpy.context.object
bpy.context.scene.render.image_settings.file_format = "PNG"
bpy.data.scenes["Scene"].render.filepath = "plane.png"
bpy.ops.render.render(write_still=True)

画像はカメラから見た結果です。視点が自由に選べるのは楽しいですね。
f:id:gangannikki:20181111171852j:plain

3. 板や背景をいじってみる

参考記事ではワイヤフレームにしたり、いろいろかっこよくしてました。なので、真似していきます。

まずは背景を暗くしていきます。Lampのタイプも変えておきます。

#  world
bpy.context.scene.world.horizon_color = (0.0, 0.0, 0.0)
#  lamp add
bpy.ops.object.lamp_add(type="HEMI", location=(0.0, 0.0, 2.0))

f:id:gangannikki:20181111172332p:plain:w300

次に、板をワイヤフレームにしていきます。

#  plane add
bpy.ops.mesh.primitive_plane_add(location=(0,0,0))
bpy.context.scene.objects.active = bpy.data.objects["Plane"]
bpy.ops.object.modifier_add(type="WIREFRAME")
bpy.context.object.modifiers["Wireframe"].thickness = 0.01

f:id:gangannikki:20181111172357p:plain:w300

4. 螺旋や回転を追加してかっこよくする

forループを用いてこのワイヤフレームを100個配置します。全体が入るようにカメラにも少し修正を加えます。
plane部分

#  plane add
for i in range(0, 100):
    bpy.ops.mesh.primitive_plane_add(radius=(i/100),
                                     location=(0,0,0),
                                     rotation=(math.pi*1/2, 0, math.pi*i*10/360))

#  modifier
for item in bpy.context.scene.objects:
    if item.type == "MESH":
        bpy.context.scene.objects.active = bpy.data.objects[item.name]
        bpy.ops.object.modifier_add(type="WIREFRAME")
        bpy.context.object.modifiers["Wireframe"].thickness = 0.02

camera部分

#  camera add
bpy.ops.object.camera_add(location=(5.0, 0.0, 0.0))
bpy.data.objects["Camera"].rotation_euler = (math.pi*1/2, 0, math.pi*1/2)

描画(render)部分

#  render
bpy.context.scene.render.resolution_x = 1000
bpy.context.scene.render.resolution_y = 1000


すごくかっちょいいですね。こういうモデリングはかっこいいのでやってて楽しいです。
f:id:gangannikki:20181111172807p:plain


今度はY軸方向に変化を与えていきます。

#  plane add
for i in range(0, 100):
    bpy.ops.mesh.primitive_plane_add(radius=(i*1.1/100),
                                     location=(0,0,0),
                                     rotation=(math.pi*1/2, math.pi*i*8.2/360, math.pi*i*10/360))

少し変化を与えただけでオブジェクト感が増しましたね。
f:id:gangannikki:20181111173149p:plain

以下の部分を変更すると

bpy.context.object.modifiers["Wireframe"].thickness = 0.0025
bpy.context.object.modifiers["Wireframe"].use_boundary = True

f:id:gangannikki:20181111173306p:plain
こんな感じで少し細いものになりました。

最終的なコード

#------------------------------------------------------------
#
#   pythonでBlender
#       spiral_wireframe.py
#
#------------------------------------------------------------
import bpy
import math

#  world
bpy.context.scene.world.horizon_color = (0.0, 0.0, 0.0)

#  reset objects
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete(True)

#  plane add
for i in range(0, 100):
    #  x,z軸のみ変化
#    bpy.ops.mesh.primitive_plane_add(radius=(i/100),
#                                     location=(0,0,0),
#                                     rotation=(math.pi*1/2, 0, math.pi*i*10/360))
    #  y軸にも変化追加
    bpy.ops.mesh.primitive_plane_add(radius=(i*1.1/100),
                                     location=(0,0,0),
                                     rotation=(math.pi*1/2, math.pi*i*8.2/360, math.pi*i*10/360))

#  modifier
for item in bpy.context.scene.objects:
    if item.type == "MESH":
        bpy.context.scene.objects.active = bpy.data.objects[item.name]
        bpy.ops.object.modifier_add(type="WIREFRAME")
        bpy.context.object.modifiers["Wireframe"].thickness = 0.0025
        bpy.context.object.modifiers["Wireframe"].use_boundary = True

#  lamp add
bpy.ops.object.lamp_add(type="HEMI", location=(0.0, 0.0, 2.0))

#  camera add
bpy.ops.object.camera_add(location=(5.0, 0.0, 0.0))
bpy.data.objects["Camera"].rotation_euler = (math.pi*1/2, 0, math.pi*1/2)

#  render
bpy.context.scene.render.resolution_x = 1000。
bpy.context.scene.render.resolution_y = 1000
bpy.context.scene.render.resolution_percentage = 100
bpy.context.scene.camera = bpy.context.object
bpy.context.scene.render.image_settings.file_format = "PNG"
bpy.data.scenes["Scene"].render.filepath = "plane7.png"
bpy.ops.render.render(write_still=True)

まとめ

前回に引き続きBlenderを使用しました。
Pythonで書けるので今のところとても使いやすいです。時間があれば、Blenderを調べた際によく出てくるキャラのモデリングなども試してみます。


研究的には3DCGがメインではなく、作成物を元にハードに実装するのがメインです。
前回のエラーは1つ改善したので、あとは保存するだけです。こちらは次回記事にまとめていきます。


知らないことを知るのは楽しいので、日々がんばります。