OneonetのPyBE

Python,Blender,Excelのいろいろ

ブレンダーモデルをPythonスクリプトとしてエクスポートする

ブログの趣旨的になんでもPythonで表現しないといけないのですが、メッシュを操作してコンソールを確認してメモする繰り返しがあまりテンションが上がりません。ということで思う存分メッシュを配置して動かして大きくして小さくしたところで、出来上がった状態をいきなりPythonスクリプトに変換するスクリプトを作成しました。

ループでパラメタを確認して文字列に落とし、最後にファイルに保存するスクリプトです。メッシュは複数対応できるようになっていて、位置(location)、サイズ(scale)、回転(rotation_euler)については情報を収集しています。キューブ以外でも可能ですが、ポリゴンの数が桁違いなのでとても長いスクリプトになります。

こちらのサイトを参考にさせて頂きました。複数メッシュの対応と位置、サイズ、回転の情報収集を付与しております。
blender.stackexchange.com

■■■Blenderはこんな状態
f:id:oneonet:20220316160226p:plain

■■■Pythonスクリプトを作成するスクリプト

#blender 3.0.0で動作確認
import bpy

s = "import bpy\n"

for ob in bpy.data.objects:
    if ob and ob.type == "MESH":
        data = ob.data

        faces = ",\n         ".join(f'{p.vertices[:]}' for p in data.polygons)
        verts = ",\n         ".join(f"{v.co[:]}"  for v in data.vertices)
        location = "".join(f"{ob.location[:]}")
        scale = "".join(f"{ob.scale[:]}")
        rotation_euler = "".join(f"{ob.rotation_euler[:]}")

        s = s + f"""

verts = ({verts})

faces = ({faces})

scene = bpy.context.scene
me = bpy.data.meshes.new("{data.name}")
me.from_pydata(verts, [], faces)
ob = bpy.data.objects.new("{data.name}", me)
ob.location = {location}
ob.scale = {scale}
ob.rotation_euler = {rotation_euler}
scene.collection.objects.link(ob)

"""

with open('c:/tmp/make_primitive.py', 'a') as f:
    print(s, file=f) 

■■■生成されたスクリプト
Blenderを日本語化しているため最初からのキューブは"Cube"、追加すると"立方体"になるようです。

import bpy

verts = ((1.0, 1.0, 1.0),
         (1.0, 1.0, -1.0),
         (1.0, -1.0, 1.0),
         (1.0, -1.0, -1.0),
         (-1.0, 1.0, 1.0),
         (-1.0, 1.0, -1.0),
         (-1.0, -1.0, 1.0),
         (-1.0, -1.0, -1.0))

faces = ((0, 4, 6, 2),
         (3, 2, 6, 7),
         (7, 6, 4, 5),
         (5, 1, 3, 7),
         (1, 0, 2, 3),
         (5, 4, 0, 1))

scene = bpy.context.scene
me = bpy.data.meshes.new("Cube")
me.from_pydata(verts, [], faces)
ob = bpy.data.objects.new("Cube", me)
ob.location = (0.0, 0.0, 0.0)
ob.scale = (1.0, 1.0, 1.0)
ob.rotation_euler = (0.0, 0.0, 0.0)
scene.collection.objects.link(ob)

verts = ((-1.0, -1.0, -1.0),
         (-1.0, -1.0, 1.0),
         (-1.0, 1.0, -1.0),
         (-1.0, 1.0, 1.0),
         (1.0, -1.0, -1.0),
         (1.0, -1.0, 1.0),
         (1.0, 1.0, -1.0),
         (1.0, 1.0, 1.0))

faces = ((0, 1, 3, 2),
         (2, 3, 7, 6),
         (6, 7, 5, 4),
         (4, 5, 1, 0),
         (2, 6, 4, 0),
         (7, 3, 1, 5))

scene = bpy.context.scene
me = bpy.data.meshes.new("立方体")
me.from_pydata(verts, [], faces)
ob = bpy.data.objects.new("立方体", me)
ob.location = (1.4182631969451904, 4.194612503051758, 0.7980197072029114)
ob.scale = (1.6070706844329834, 1.6070706844329834, 1.6070706844329834)
ob.rotation_euler = (-0.6515693664550781, 0.14909927546977997, -0.39666253328323364)
scene.collection.objects.link(ob)