From BlenderWiki

Jump to: navigation, search

オブジェクトを作る3つの方法

この例では、Python からオブジェクトを複数の方法で作れることを見ていきます。

データ方式

データ方式は、Blender 内部のデータ格納法に非常に似ています。

  • データを追加し、次にオブジェクトを追加します。メッシュであれば:
me = bpy.data.meshes.new(meshName)
ob = bpy.data.objects.new(obName, me)

アーマチュアであれば:

amt = bpy.data.armatures.new(amtname)
ob = bpy.data.objects.new(obname, amt)
  • オブジェクトを現在のシーンにリンクして、アクティブにします。新たに作ったオブジェクトはアクティブや選択状態にすることもできます。このコードはどの種類のオブジェクトでも同じです。
scn = bpy.context.scene
scn.objects.link(ob)
scn.objects.active = ob
ob.select = True
  • データを埋めます。メッシュの例では、頂点と面のリストを追加します。
me.from_pydata(verts, [], faces)

アーマチュアの例では、edit mode に切り替えてボーンを追加します。

bpy.ops.object.mode_set(mode='EDIT')
bone = amt.edit_bones.new('Bone')
bone.head = (0,0,0)
bone.tail = (0,0,1)
  • 最終的に、通常は編集したデータを更新する必要があります。メッシュの例では更新関数を明示的に呼びます。
me.update()

オブジェクトモードに切り替えるとアーマチュアは暗黙的に更新されます。

bpy.ops.object.mode_set(mode='OBJECT')

Operator(演算)方式

operator 方式はオブジェクトとデータブロックを同時に追加します。データブロックは初めは空で、あとで実際のデータを入れる必要があります。

  • bpy.ops.object.add operator でオブジェクトを追加します。これで、データ方式では手動で行う必要のあったいくつかの事が、自動的に行われます: オブジェクトデータ(メッシュやアーマチュア)を作り、オブジェクトをシーンにリンクし、アクティブにして選択状態にします。一方、オブジェクトにデータを入れる必要があります。これは常にアクティブオブジェクトを指す bpy.context.data を使うと簡単です。
    メッシュオブジェクトを追加するには、次を実行します。
bpy.ops.object.add(type='MESH')
ob = bpy.context.object
me = ob.data

アーマチュアを追加します:

bpy.ops.object.add(
type='ARMATURE',
enter_editmode=True,
location=origin)
ob = bpy.context.object
amt = ob.data
  • データ方式と同じように、使う前に実際のデータが入り、更新されている必要があります。メッシュでは頂点と面を追加します:
me.from_pydata(verts, [], faces)
me.update()

アーマチュアではボーンを追加します:

bone = amt.edit_bones.new('Bone')
bone.head = (0,0,0)
bone.tail = (0,0,1)
bpy.ops.object.mode_set(mode='OBJECT')

アーマチュアは作成時にすでに edit mode に入っているので、明示的に edit mode に入る必要がないことに注意してください。

プリミティブ方式

プリミティブ型のオブジェクトを作りたいなら、望みのプロパティを持ったプリミティブを作れる operator を探します。

  • cone は実際のところ pyramid によく似ています。

4つの側面を持つ pyramid メッシュを作るには:

bpy.ops.mesh.primitive_cone_add(
vertices=4,
radius=1,
depth=1,
cap_end=True)

一方、次のコードは1つのボーンを持つアーマチュアを追加します。

bpy.ops.object.armature_add()
bpy.ops.transform.translate(value=origin)
  • operator 方式と同じで、新たに作成したオブジェクトは bpy.context.object で取得できます。
ob = bpy.context.object
me = ob.data

比較

プリミティブ方式が一番簡単ですが、使えるのは都合のよいプリミティブが利用できる場合だけです。また、このプログラム例でさえも、作成したのは他の方式のものとわずかに異なる pyramid メッシュでした。底は1枚の四角形ではなく、底の中心点を共有する4つの三角形でできています。他の2つの方式はだいたい同じです。

プリミティブは特に単純である必要はありません。猿のメッシュや人間のリグを作るプリミティブがあります。しかしながらプリミティブ方式で作れるのは常に、事前に作られたオブジェクトに限られます。

この記事の例では3つ全ての方式を使っています。 Code Snippets Objects.png

#----------------------------------------------------------
# File objects.py
#----------------------------------------------------------
import bpy
import mathutils
from mathutils import Vector
 
def createMeshFromData(name, origin, verts, faces):
    # メッシュとオブジェクトを作成
    me = bpy.data.meshes.new(name+'Mesh')
    ob = bpy.data.objects.new(name, me)
    ob.location = origin
    ob.show_name = True
 
    # シーンにオブジェクトをリンクしアクティブ化
    scn = bpy.context.scene
    scn.objects.link(ob)
    scn.objects.active = ob
    ob.select = True
 
    # 頂点と面からメッシュを作成
    me.from_pydata(verts, [], faces)
    # 新たなデータでメッシュを更新
    me.update()    
    return ob
 
def createMeshFromOperator(name, origin, verts, faces):
    bpy.ops.object.add(
        type='MESH', 
        enter_editmode=False,
        location=origin)
    ob = bpy.context.object
    ob.name = name
    ob.show_name = True
    me = ob.data
    me.name = name+'Mesh'
 
    # 頂点と面からメッシュを作成
    me.from_pydata(verts, [], faces)
    # 新たなデータでメッシュを更新
    me.update()    
    # object mode にします
    bpy.ops.object.mode_set(mode='OBJECT')
    return ob
 
def createMeshFromPrimitive(name, origin):
    bpy.ops.mesh.primitive_cone_add(
        vertices=4, 
        radius=1, 
        depth=1, 
        cap_end=True, 
        view_align=False, 
        enter_editmode=False, 
        location=origin, 
        rotation=(0, 0, 0))
 
    ob = bpy.context.object
    ob.name = name
    ob.show_name = True
    me = ob.data
    me.name = name+'Mesh'
    return ob
 
def createArmatureFromData(name, origin):
    # アーマチュアとオブジェクトを作成
    amt = bpy.data.armatures.new(name+'Amt')
    ob = bpy.data.objects.new(name, amt)
    ob.location = origin
    ob.show_name = True
 
    # シーンにオブジェクトをリンクしアクティブ化
    scn = bpy.context.scene
    scn.objects.link(ob)
    scn.objects.active = ob
    ob.select = True
 
    # ボーンを1つ作成
    bpy.ops.object.mode_set(mode='EDIT')
    bone = amt.edit_bones.new('Bone')
    bone.head = (0,0,0)
    bone.tail = (0,0,1)
    bpy.ops.object.mode_set(mode='OBJECT')
    return ob
 
def createArmatureFromOperator(name, origin):
    bpy.ops.object.add(
        type='ARMATURE', 
        enter_editmode=True,
        location=origin)
    ob = bpy.context.object
    ob.name = name
    ob.show_name = True
    amt = ob.data
    amt.name = name+'Amt'
 
    # ボーンを1つ作成
    bone = amt.edit_bones.new('Bone')
    bone.head = (0,0,0)
    bone.tail = (0,0,1)
    bpy.ops.object.mode_set(mode='OBJECT')
    return ob
 
def createArmatureFromPrimitive(name, origin):
    bpy.ops.object.armature_add()
    bpy.ops.transform.translate(value=origin)
    ob = bpy.context.object
    ob.name = name
    ob.show_name = True
    amt = ob.data
    amt.name = name+'Amt'
    return ob
 
def run(origo):
    origin = Vector(origo)
    (x,y,z) = (0.707107, 0.258819, 0.965926)
    verts = ((x,x,-1), (x,-x,-1), (-x,-x,-1), (-x,x,-1), (0,0,1))
    faces = ((1,0,4), (4,2,1), (4,3,2), (4,0,3), (0,1,2,3))
 
    cone1 = createMeshFromData('DataCone', origin, verts, faces)
    cone2 = createMeshFromOperator('OpsCone', origin+Vector((0,2,0)), verts, faces)
    cone3 = createMeshFromPrimitive('PrimCone', origin+Vector((0,4,0)))
 
    rig1 = createArmatureFromData('DataRig', origin+Vector((0,6,0)))
    rig2 = createArmatureFromOperator('OpsRig', origin+Vector((0,8,0)))
    rig3 = createArmatureFromPrimitive('PrimRig', origin+Vector((0,10,0)))
    return
 
if __name__ == "__main__":
    run((0,0,0))