MRが楽しい

MRやVRについて学習したことを書き残す

Blender 2.8のPython APIドキュメントを少しずつ読み解く 落とし穴 その11

本日は Blender2.8 の調査枠です。
Blender 2.8 の Python API ドキュメントを少しずつ読みつつ試していきます。
前回記事の続きです。
bluebirdofoz.hatenablog.com

Blender 2.8 Python API Documentation

以下のページを日本語訳しつつ実際に試して記事を進めていきます。
docs.blender.org
docs.blender.org

今日は「落とし穴」の「編集モード/メモリアクセス」と「配列の再割り当て」です。
f:id:bluebirdofoz:20200123092653j:plain

編集モード/メモリアクセス

編集モードの切替 bpy.ops.object.mode_set(mode='EDIT')/ bpy.ops.object.mode_set(mode='OBJECT') はオブジェクトデータを再割り当てします。
メッシュ頂点/ポリゴン/ UV座標、アーマチュア骨、カーブポイントなどへの参照は、編集モードを切り替えた後にアクセスすることはできません。

再アクセスできるのはデータへの参照のみです。
以下の例はクラッシュします。

mesh = bpy.context.active_object.data
polygons = mesh.polygons
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.object.mode_set(mode='OBJECT')

# this will crash
print(polygons)

f:id:bluebirdofoz:20200123092710j:plain

編集モードを切り替えた後は、オブジェクトデータに再アクセスする必要があります。
以下の例は、上記のクラッシュを回避する方法です。

mesh = bpy.context.active_object.data
polygons = mesh.polygons
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.object.mode_set(mode='OBJECT')

# polygons have been re-allocated
polygons = mesh.polygons
print(polygons)

f:id:bluebirdofoz:20200123092720j:plain

この種の問題は、オブジェクトデータを再割り当てする関数で発生する可能性があります。
編集モードを切り替えるときは最も一般的な例です。

配列の再割り当て

以下の操作を行うと、データを格納する配列が内部的に再割り当てされます。
・カーブに新しいポイントを追加する。
・メッシュに頂点/エッジ/ポリゴンを追加する。

bpy.ops.curve.primitive_bezier_curve_add()
points = bpy.context.object.data.splines[0].bezier_points
point = bpy.context.object.data.splines[0].bezier_points[0]
bpy.context.object.data.splines[0].bezier_points.add(len(points)-1)

# this will crash!
point.co = 1.0, 2.0, 3.0

f:id:bluebirdofoz:20200123092732j:plain

・成功例
f:id:bluebirdofoz:20200123092742j:plain

これは以下の対策で回避できます。
・新しい変数を追加した後にポイント変数を再割り当てする。
・ポイント自体ではなくポイントにインデックスを設定する。

最良の方法は、問題を完全に回避するため、すべてのポイントを一度にカーブに追加することです。
これは配列の再割り当てを心配する必要がなく、より高速であることを意味します。
(追加されたすべてのポイントに配列全体を再割り当てするのは非効率的であるため)

bluebirdofoz.hatenablog.com