Blender の API は bpy で始まり、データアクセス手段は
bpy.data 以下に集約されています。

例えばシーン内のオブジェクトは bpy.data.objects で取れます。
下記のように Python Console で確認できます。
(太字がキー入力です)

>>> bpy.data.objects['Cube']
bpy.data.objects['Cube']

>>> bpy.data.objects.keys()
['Camera', 'Cube', 'Lamp']

>>> bpy.data.objects.values()
[bpy.data.objects['Camera'], bpy.data.objects['Cube'], bpy.dta.objects['Lamp']]

↑Python の辞書(連想配列)のように見えますがちょっと違います。

>>> bpy.data.objects
<bpy_collection[3], BlendDataObjects>

>>> bpy.data.objects[0]
bpy.data.objects['Camera']

>>> bpy.data.objects.find('Cube')
1

>>> bpy.data.objects[1:]
[bpy.data.objects['Cube'], bpy.dta.objects['Lamp']]

↑数値 index でもアクセス可能で要素の順番が固定。
find() を使うと index を取ることが可能です。
特に for in では要素が列挙され、配列のような振る舞いをします。

>>> for a in bpy.data.objects: print( a )
<bpy_struct, Object("Camera")>
<bpy_struct, Object("Cube")>
<bpy_struct, Object("Lamp")>

key を持つがシーケンスとして扱える特殊な collection となっています。
python に慣れてないせいもありますが、
辞書のつもりで script を読んでいると少々混乱します。


● Object Type

Object の種類は type プロパティで確認できます。

>>> for a in bpy.data.objects: print( a.type )
CAMERA
MESH
LAMP

bpy.types にデータの種類一覧があります。

Types (bpy.types)

この bpy.types が Maya でいう Node に相当するもののようです。
例えば 'Cube' は bpy.types.Mesh で、独自のインスタンスととデータは
Object.data からアクセスします。

>>> bpy.data.objects['Cube'].data.vertices[1].co
Vector((1.0, -1.0, -1.0))

Object 自体が階層構造を持てるので DagNode を兼ねています。
Maya ではインスタンスである Object とメソッドでである Function が
分離していましたが、Blender はそのようなことがなくシンプルです。

Object の階層は下記のようにたどることができます。
Maya のように Transform Node が別だったりしません。

def tree( obj ):
  print( obj )
  print( obj.matrix_local )
  for child in obj.children:
    tree( child )

def root():
  for obj in bpy.data.objects:
    if not obj.parent:
      tree( obj )

root()

root の object だけ得るには
[obj for obj in bpy.data.objects if not obj.parent]
で出来ます。

bpy.data.objects はすべてのオブジェクトを列挙しますが、
同時に data type ごとの collection も持っているようです。

>>> bpy.data.objects.keys()
['Camera', 'Cube', 'Lamp', 'Sphere', 'Suzanne']

>>> bpy.data.meshes.keys()
['Cube', 'Sphere', 'Suzanne']

bpy.data.meshes に入っているのはデータそのもの、Object.data です。
こちらは階層などの Node 情報を含んでいません。

>>> bpy.data.meshes['Cube'].vertices[1].co
Vector((1.0, -1.0, -1.0))

Object を削除しても Mesh は残っているようです。
この辺の Blender の内部挙動はまだ私の方がきちんと理解しておりません。

matrix_local はドキュメント Object(ID) では float array
と書かれてますが mathutils.Matrix を返すようです。


● Mesh のアクセス方法

Mesh には形状データが入っています。
頂点データ自体は Mesh.vertices ですが、下記ページの解説にあるように
edge, loop, polygon と 3種類のインデックスがあります。

Mesh(ID)

・MeshVertex : 頂点データそのもの
・MeshEdge : 2頂点の index
・MeshLoop : 1頂点 + edge の index
・MeshPolygon : n個の loop の index

mesh= Suzanne
<bpy_collection[500], MeshPolygons>
<bpy_collection[507], MeshVertices>
<bpy_collection[1968], MeshLoops>
<bpy_collection[1005], MeshEdges>
mesh= Cube
<bpy_collection[6], MeshPolygons>
<bpy_collection[8], MeshVertices>
<bpy_collection[24], MeshLoops>
<bpy_collection[12], MeshEdges>
mesh= Sphere
<bpy_collection[512], MeshPolygons>
<bpy_collection[482], MeshVertices>
<bpy_collection[1984], MeshLoops>
<bpy_collection[992], MeshEdges>

Mesh 内の MeshPolygon (Face) の列挙は下記の通り。

def shape( obj ):
  mesh= obj.data
  for poly in mesh.polygons:
    print( poly )

MeshPolygon に含まれる頂点 (Face Vertex) を得るには下記の通り。

# Loop を使った場合
def shape( obj ):
  mesh= obj.data
  for poly in mesh.polygons:
    for id in range( poly.loop_start, poly.loop_start + poly.loop_total ):
      print( mesh.verticies[ mesh.loops[ id ].vertex_index ].co )

MeshPolygon に含まれる MeshLoop をたどって MeshLoop.vertex_index を
参照しています。
なお、Loop を使わなくても MeshPolygon.vertices で直接頂点 index を
取れることがわかりました。

def shape( obj ):
  mesh= obj.data
  for poly in mesh.polygons:
    for ver in poly.vertices:
      print( mesh.vertices[ ver ].co )

ただし、mesh.loops の参照用 index 値 (「Loop を使った場合」の id ) は
uv など他のデータアクセスにも使います。
loop は Face Vertex 単位のデータとなり、Cube の場合 24 個あります。
一見複雑ですが「Loop を使った場合」の方が都合が良いようです。


● 法線

頂点データ MeshVertex に直接頂点法線が格納されています。
頂点座標が共有される場合法線も共有されており、この値は
ハードエッジになりません。

頂点とは別に MeshPolygon に面法線が格納されており、プロパティ
Mesh.use_smooth の値によってこの両者を使い分ける必要があるようです。


● UV / 頂点カラー

Mesh.uv_layers に格納されます。値そのものは MeshUVLoop.uv です。
uv_layers が MeshUVLoopLayer で data に MeshUVLoop が頂点分 (Loop 数分)
格納されます。

>>> len(bpy.data.objects['Cube'].data.uv_layers)
1

>>> len(bpy.data.objects['Cube'].data.uv_layers[0].data)
24

>>> bpy.data.objects['Cube'].data.uv_layers[0].data[0].uv
Vector((0.0), 0.0))

>>> bpy.data.objects['Cube'].data.uv_layers.active.data[0].uv
Vector((0.0), 0.0))

頂点カラーも全く同じで Mesh.vertex_colors に入ります。
今までの情報を取り出すコードがこれです。

def shape( obj ):
  print( 'mesh=', obj.name )
  mesh= obj.data
  uv_array= mesh.uv_layers.active.data if len(mesh.uv_layers) else None
  vcolor_array= mesh.vertex_colors.active.data if len(mesh.vertex_colors) else None
  for poly in mesh.polygons:
    for id in range( poly.loop_start, poly.loop_start + poly.loop_total ):
      vertex= mesh.vertices[ mesh.loops[ id ].vertex_index ]
      position= vertex.co
      normal= vertex.normal
      if not poly.use_smooth:
        normal= poly.normal
      print( 'pos=', position )
      print( 'normal=', normal )
      if uv_array:
        uv= uv_array[id].uv
        print( 'uv=', uv )
      if vcolor_array:
        vcolor= vcolor_array[id].color
        print( 'vcolor=', vcolor )


def tree( obj ):
  if obj.type == 'MESH':
      shape( obj )
  #print( 'matrix=', obj.matrix_local )
  for child in obj.children:
    tree( child )

def root():
  for obj in bpy.data.objects:
    if not obj.parent:
      tree( obj )

root()

それぞれ最初の(active な) UV set と VertexColor しか参照していないので注意してください。
uv_array, vcolor_array の参照に Loop と同じ id を使っていることがわかります。
Matrix 同様、ドキュメントではただの array ですが実際に返す値は
mathutils.Vector, mathutils.Color となっています。

続きます


関連エントリ
Blender 2.6 の Export plug-in を作る (1)