書き物

技術とか作った物の話とか愚痴文句感想など

Blender のアドオンを作る準備

KinectBlenderモーションキャプチャするために AMBloop(https://github.com/asahiufo/AMBloop)を使ってがんばっていますが、どうにも希望通り動作させることが出来ないかつ、ソース修正の方法が分からないということで、Bloop を参考にモーションキャプチャツールを自作することにしました。C#Kinect データ送信プログラムはなんとなく出来たので、次は Blender でデータ受信、メッシュへ適用、アニメーションとして録画する Blender アドオンを作らなければなりません。 Python は触ったことがないかつ、Blender のアドオンを作るのも初めてなので、まず開発の進め方を調べてみました。(自分の作りたいものに特化しています。Python の文法周りは、都度都度調べるということで無視です。)

対象環境

1. どんなのを作りたいのか ↓のように、Bloop と同じような形で作る予定です。 Result menu

2. 調べ方 やっぱり公式が良さそうです。(英語) Blender Documentation Contents — Blender 2.64.1 - API documentation

以下のようなコアとなる処理は Bloop を参考にするとします。

  • OSC(Open Sound Control)データの受信
  • メッシュの座標へ適用
  • 録画

まずは Bloop での処理の頭を見てみます。 多分このあたりで Blender 上での GUI を記述しているのではないかと。 AMBloop/nui/init.py at master · asahiufo/AMBloop · GitHub import bpy from .nui_sensor import NUISensor #@UnresolvedImport from .nui_sensor import NUIUser #@UnresolvedImport from .nui_draw import NUI_draw_end #@UnresolvedImport from .nui_panel import NUIPanel #@UnresolvedImport from .nui_panel import NUIToggleDraw #@UnresolvedImport from .nui_panel import NUIProps #@UnresolvedImport

bl_info = { “name”: “NUI Interface”, “description”: “Provides access to Kinect NUI data via OSCeleton”, “author”: “Florian Biermann”, “version”: (1,0), “blender”: (2, 5, 9), “api”: 31236, “location”: “bpy.nui”, “warning”: “A user property, like ‘head’, returns a tuple of (Vector, Quaternion).”, “wiki_url”: “”, “tracker_url”: “”, “category”: “Development”}

def register(): bpy.utils.register_class(NUIToggleDraw) bpy.utils.register_class(NUIPanel) bpy.utils.register_class(NUIProps) bpy.types.WindowManager.nui_props = bpy.props.PointerProperty(type=NUIProps) bpy.nui = NUISensor(mode=“oscpuppet”, debug=False) #bpy.nui = NUISensor(mode=“mssdk”)

def unregister(): bpy.utils.unregister_class(NUIToggleDraw) bpy.utils.unregister_class(NUIPanel) bpy.utils.unregister_class(NUIProps) del bpy.nui AMBloop/nui/nui_panel.py at master · asahiufo/AMBloop · GitHub import bpy from .nui_draw import NUI_draw_begin from .nui_draw import NUI_draw_end

class NUIPanel(bpy.types.Panel):

bl_label = "NUI"
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'

@classmethod
def poll(cls, context):
    return hasattr(bpy, "nui")


def draw(self, context):
    col = self.layout.column(align=False)
    if bpy.nui.draw:
        col.operator("nui.toggle_draw", text="Stop user display")
    else:
        col.operator("nui.toggle_draw", text="Start user display")

    col = self.layout.column(align=True)
    col.prop(context.window_manager.nui_props, "offset_x")
    col.prop(context.window_manager.nui_props, "offset_y")

    if not bpy.nui.mode == "mssdk":
        col = self.layout.column(align=True)
        col.prop(context.window_manager.nui_props, "sensor_angle")

class NUIToggleDraw(bpy.types.Operator):

bl_idname = "nui.toggle_draw"
bl_label = "Toggle NUI user display"

@classmethod
def poll(cls, context):
    return NUIPanel.poll(context)


def execute(self, context):
    if bpy.nui.draw:
        NUI_draw_end(context)
    else:
        NUI_draw_begin(context)
    return {"FINISHED"}

class NUIProps(bpy.types.PropertyGroup): do_draw = bpy.props.BoolProperty(name=“Draw user”, default = True) offset_x = bpy.props.IntProperty(name=“Screen offset X”, default=200) offset_y = bpy.props.IntProperty(name=“Screen offset Y”, default=200) sensor_angle = bpy.props.IntProperty(name=“Sensor angle”, default=0, soft_min=-31, soft_max=31)

特に↓のあたりは怪しそうです。 class NUIPanel(bpy.types.Panel):

bl_label = "NUI"
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'

公式ドキュメントを漁ってみると、bpy.types.Panel のサンプルがありました。 Quickstart Introduction — Blender 2.64.1 - API documentation まずはこれを動かしてみようと思います。

3. スクリプトの実行確認

3.1. Blender 起動 Blender 起動

3.2. 新しいエディタを表示 新しいエディタ表示

3.3. TextEditor 表示 TextEditor 表示 TextEditor の下の「-」印を押しておき、右に 3 つ並んでいる□のアイコンを 3 つともクリックしておくと、エディタが見やすくなりそうです。 TextEditor 設定

3.4. スクリプト貼り付け 「+ New」ボタンを押してソースを新規作成します。(名前は適当に “panel.py” としておきます。) ここに公式ドキュメントの bpy.types.Panel のサンプルを貼り付けるのですが、今回作りたいものに合わせて以下のとおり修正します。 import bpy

class AMK2BPanel(bpy.types.Panel): “”“Creates a Panel in the Object properties window”“” bl_label = “AMK2B” bl_space_type = ‘VIEW_3D’ bl_region_type = ‘TOOLS’

def draw(self, context):
    layout = self.layout

    obj = context.object

    row = layout.row()
    row.label(text="Hello world!", icon='WORLD_DATA')

    row = layout.row()
    row.label(text="Active object is: " + obj.name)
    row = layout.row()
    row.prop(obj, "name")

    row = layout.row()
    row.operator("mesh.primitive_cube_add")

def register(): bpy.utils.register_class(AMK2BPanel)

def unregister(): bpy.utils.unregister_class(AMK2BPanel)

if name == “main”: register() 結果こんな感じです。 貼り付け結果

3.5. 実行結果確認 TextEditor 下の 「Run Script」ボタンを押して実行します。 実行すると、「3D View」パネルの左("Object Tools" があるあたり)に “AMK2B” というパネルが追加されるはずです。 実行前 実行前 実行後 実行後 変化無し・・・。 どうやら、パネルの表示を変えた場合、BlenderGUI の表示を更新してやらなければならないようです。 表示の更新は、エディタの表示幅等を弄ればよいようです。 以下では、「3D View」エディタの幅を右へ少し広げた結果です。 表示更新 新しい Panel が追加されました! これを繰り返せば、編集、実行結果確認を進めていけそうです。

終わりに Blender のアドオンを作る場合、一旦 Blender 上でファイル編集をして、出来上がったらソースを別ファイルやフォルダに格納すれば良いのでしょうか?この辺りは作りながら様子を見ようと思います。