🐵

Blender Pythonでメッシュの各ポリゴンの各頂点の頂点座標値、Shapekeyごとの頂点座標値、UV座標値、頂点カラーを取得する

2024/02/15に公開

概要

メッシュの各ポリゴンの各頂点の
 ・頂点座標値
 ・各Shapekeyに登録されている頂点座標値
 ・UV座標値
 ・頂点カラー
を取得する方法を紹介します

今回は例としてデフォルトキューブを使って情報を取得してみます

環境

  • Blender 3.3

Pythonスクリプトと実行方法

  1. Blenderを開き、デフォルトキューブを消さずに「ウィンドウ」タブの「システムコンソール切り替え」をクリックし、スクリプトの実行結果やエラーが見えるようにする
  2. 「Sclipting」タブの「+新規」ボタンをクリックして以下のPythonスクリプトを貼り付け、「▶」ボタンをクリックし、スクリプトを実行する


Shapekeyと頂点カラーはデフォルトキューブには最初から存在しないので、スクリプトで追加しています

import bpy


# メッシュを取得 (選択されているメッシュを取得する場合はbpy.context.view_layer.objects.active)
Mesh = bpy.data.objects["Cube"]                 # Cubeという名前のメッシュを取得
Mesh.select_set(state=True)                     # メッシュをアクティブに設定


# メッシュにShapekeyが2つ無かったら追加する
if not Mesh.data.shape_keys:
    bpy.ops.object.shape_key_add()
    Mesh.data.shape_keys.key_blocks[0].name = "Basis"
if 1 == len(Mesh.data.shape_keys.key_blocks):
    bpy.ops.object.shape_key_add()
    Mesh.data.shape_keys.key_blocks[1].name = "Key 1"

# メッシュに頂点カラーが無かったら追加する
if not Mesh.data.vertex_colors:
    bpy.ops.mesh.vertex_color_add() # Blender3.4以降はMesh.data.vertex_colors.new()で動くはず
    Mesh.data.vertex_colors[0].name = "Col"


# メッシュの各ポリゴンごとにループ
for Poly in Mesh.data.polygons:

    # 現在のポリゴンのインデックス番号と辺の数を表示
    print("----------------------------------------------------------------------")
    print("Polygon index: %d, Number of sides: %d" % (Poly.index, Poly.loop_total))
    
    # 現在のポリゴンの各頂点ごとにループ
    for LoopIndex in range(Poly.loop_start, Poly.loop_start + Poly.loop_total):
        
        # 現在の頂点のインデックス番号を取得
        VertexIndex = Mesh.data.loops[LoopIndex].vertex_index

        # 現在の頂点の座標値を取得
        VertexPos = Mesh.data.vertices[VertexIndex].co

        # 現在の頂点の各Shapekeyに登録されている座標値を取得 (BasisとKey 1)
        Shapekey0_Pos = Mesh.data.shape_keys.key_blocks[0].data[VertexIndex].co
        Shapekey1_Pos = Mesh.data.shape_keys.key_blocks[1].data[VertexIndex].co
        
        # 現在の頂点のUV座標値を取得
        UvPos = Mesh.data.uv_layers[0].data[LoopIndex].uv

        # 現在の頂点の頂点カラーを取得
        VertexColor = Mesh.data.vertex_colors[0].data[LoopIndex].color
        
        # 取得した現在の頂点の情報を表示
        print("")
        print("  VertexIndex :", VertexIndex)
        print("    VertexPos :", *VertexPos)
        print("Shapekey0_Pos :", *Shapekey0_Pos)
        print("Shapekey1_Pos :", *Shapekey1_Pos)
        print("        UvPos :", *UvPos)
        print("  VertexColor :", *VertexColor)
        

実行結果

デフォルトキューブは6個の四角面で構成されているので、Polygon indexが6回表示され、各Polygon index内でVertexIndexが4回表示されていれば成功です

Shapekey(Key 1)の頂点を移動させたり、UVをずらしたり、頂点ペイントを行ったりすると、スクリプトの実行結果も変わるはずです

つまづきやすいポイント

最初のうちは頭がこんがらがるのですが、頂点1個あたりにUV座標1個と頂点カラー1個が割り当てられているのではなく、「面と頂点の組み合わせ」ごとにUV座標と頂点カラーが割り当てられていることに注意してください

今回のデフォルトキューブでは頂点数が8個ですが、
UV座標と頂点カラーはそれぞれ 6(面の数) x 4(各面の頂点数) = 24個 存在します

各頂点の情報の変更例

今回のスクリプトでは各頂点の情報を表示しているだけですが、もちろん変更も行えます。
例えば頂点カラーの値を変更したければ、

VertexColor = Mesh.data.vertex_colors[0].data[LoopIndex].color

と書かれている右辺の部分を左辺に持ってきて

Mesh.data.vertex_colors[0].data[LoopIndex].color = [1, 0, 0, 1] # RGBAで赤色を指定

のように、リスト形式で値を直接指定できます

参考にさせていただいたサイト

https://docs.blender.org/api/3.3/bpy.types.Mesh.html
https://qiita.com/kenyoshi17/items/b93bbba6451e3c6017e5
https://qiita.com/SaitoTsutomu/items/05b2481e5d1d98652043

Discussion