Dev:JA/2.5/Py/Scripts/Cookbook/Code snippets/Three ways to create objects
オブジェクトを作る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つの方式はだいたい同じです。
プリミティブは特に単純である必要はありません。猿のメッシュや人間のリグを作るプリミティブがあります。しかしながらプリミティブ方式で作れるのは常に、事前に作られたオブジェクトに限られます。
#----------------------------------------------------------
# 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))