カテゴリー別アーカイブ: スクリプト

Blender 2.5 Python スクリプトによるエクスポータの作成 – UV座標の出力 –


せっかくここまでやったので、UV 座標の出力もやってしまいます。今まで通りドキュメントを参照しながらやるのですが、UV まわりは少しデータ構造が複雑ですね。テクスチャを複数持っていたり、一つの頂点が複数の UV 座標を持っていることもあるようです。とりあえず今回は最初のデータのみを扱うことにしました。

これだけのデータがあれば、簡単なプログラムには使えそうですね。

def write_some_data(context, filepath, use_some_setting):
    print("running write_some_data...")
    f = open(filepath, 'w')
    obj = bpy.context.selected_objects[0]
    mesh = obj.data
 
    if obj.mode == 'OBJECT':
        bpy.ops.object.editmode_toggle()
    bpy.ops.mesh.quads_convert_to_tris()
    bpy.ops.object.editmode_toggle()
 
    f.write( "Model : \"%s\" {\n" % obj.name )
 
    # Material
    material = obj.active_material
    if material:
        f.write( "Material : \"%s\" {\n" % material.name )
        f.write( "Diffuse : { %f, %f, %f }\n" % ( material.diffuse_color.r, material.diffuse_color.g, material.diffuse_color.b ) )
        f.write( "Specular : { %f, %f, %f }\n" % ( material.specular_color.r, material.specular_color.g, material.specular_color.b ) )
        f.write( "Translucency : { %f }\n" % material.translucency )
        f.write( "Fresnel : { %f, %f }\n" % ( material.diffuse_fresnel, material.diffuse_fresnel_factor ) )
        f.write( "} // Material\n" )
 
    # Index
    f.write( "Faces : %d {\n" % len( mesh.faces ) )
    for face in mesh.faces:
        f.write( "%d { " % len( face.vertices ) )
        for index in face.vertices:
            f.write( "%d, " % index )
        f.write( "}\n" )
    f.write( "} // Faces\n" )
 
    # Vertex
    f.write( "Vertexes : %d {\n" % len( mesh.vertices ) )
    for vertex in mesh.vertices:
        f.write( "%d { %f, %f, %f }\n" % ( vertex.index, vertex.co.x, vertex.co.y, vertex.co.z ) )
    f.write( "} // Vertexes\n" )
 
    # Normals
    f.write( "Normals : %d {\n" % len( mesh.vertices ) )
    for vertex in mesh.vertices:
        f.write( "%d { %f, %f, %f }\n" % ( vertex.index, vertex.normal.x, vertex.normal.y, vertex.normal.z ) )
    f.write( "} // Normals\n" )    
 
    # UVs
    if mesh.uv_textures:
        f.write( "UVs : %d{\n" % len( mesh.uv_textures[0].data ) )
        index = 0
        for face in mesh.uv_textures[0].data:
            f.write( "%d { %f, %f }\n" % ( index, face.uv1.x, 1.0 - face.uv1.y ) )
            index += 1
            f.write( "%d { %f, %f }\n" % ( index, face.uv2.x, 1.0 - face.uv2.y ) )
            index += 1
            f.write( "%d { %f, %f }\n" % ( index, face.uv3.x, 1.0 - face.uv3.y ) )
            index += 1
        f.write( "} // UVs\n" )
 
    f.write( "} // Model\n")
    f.close()
    return {'FINISHED'}

Blender 2.5 Python スクリプトによるエクスポータの作成 – 四角形ポリゴンの三角形化 –


ここまで作ったスクリプトで、デフォルトで表示されている立方体をエクスポートすると、面を構成する頂点数が4つになってしまいます。プログラムで使う場合は三角形ポリゴンを使うことが多いのでこれだと何かと不都合です。とはいえ、Blender ではポリゴンの三角形化は “Edit Mode” に入って分割したい頂点を選んで Ctrl-t するだけです。

ですので、三角形化してからエクスポートすれば良いのですが、せっかくなのでその部分も自動化したいところです。Blender2.5 系では API というかスクリプティングとの親和性も高くなっていてやりたいことをやりやすく、調べやすくなっている印象です。

下図は、ここまでの操作を行った際のスクリーンショットです。上に引いてある赤線は直前に行った操作が API ではどのように表現するかが出力されています。

つまり “bpy.ops.object.editmode_toggle()” で、”Object Mode” と “Edit Mode” を切り替えて(つまり Tab キーの操作)、”bpy.ops.mesh.quads_convert_to_tris()” で Ctrl-t 相当の操作を行っているということです。これらを追加すれば三角形化から出力までを自動化できます。

今回は “Object Mode” だったら “Edit Mode” に切り替えて、三角形化したらまた “Object Mode” に戻すようにしています。

ちなみにボタンなどにマウスカーソルを重ねた時に出てくるツールチップには上図の下の赤線のように、説明と共に(あれば)ショートカットキー、その操作のスクリプトも同時に出てきます。なので、自動化したい操作があれば、その順番でツールチップに出てくるスクリプトを並べて行けば基本的なところはそろえることが出来ます。

def write_some_data(context, filepath, use_some_setting):
    print("running write_some_data...")
    f = open(filepath, 'w')
    obj = bpy.context.selected_objects[0]
    mesh = obj.data
 
    if obj.mode == 'OBJECT':
        bpy.ops.object.editmode_toggle()
    bpy.ops.mesh.quads_convert_to_tris()
    bpy.ops.object.editmode_toggle()
 
    f.write( "Model : \"%s\" {\n" % obj.name )
 
    # Material
    material = obj.active_material
    if material:
        f.write( "Material : \"%s\" {\n" % material.name )
        f.write( "Diffuse : { %f, %f, %f }\n" % ( material.diffuse_color.r, material.diffuse_color.g, material.diffuse_color.b ) )
        f.write( "Specular : { %f, %f, %f }\n" % ( material.specular_color.r, material.specular_color.g, material.specular_color.b ) )
        f.write( "Translucency : { %f }\n" % material.translucency )
        f.write( "Fresnel : { %f, %f }\n" % ( material.diffuse_fresnel, material.diffuse_fresnel_factor ) )
        f.write( "} // Material\n" )
 
    # Index
    f.write( "Faces : %d {\n" % len( mesh.faces ) )
    for face in mesh.faces:
        f.write( "%d { " % len( face.vertices ) )
        for index in face.vertices:
            f.write( "%d, " % index )
        f.write( "}\n" )
    f.write( "} // Faces\n" )
 
    # Vertex
    f.write( "Vertexes : %d {\n" % len( mesh.vertices ) )
    for vertex in mesh.vertices:
        f.write( "%d { %f, %f, %f }\n" % ( vertex.index, vertex.co.x, vertex.co.y, vertex.co.z ) )
    f.write( "} // Vertexes\n" )
 
    # Normals
    f.write( "Normals : %d {\n" % len( mesh.vertices ) )
    for vertex in mesh.vertices:
        f.write( "%d { %f, %f, %f }\n" % ( vertex.index, vertex.normal.x, vertex.normal.y, vertex.normal.z ) )
    f.write( "} // Normals\n" )    
 
    f.write( "} // Model\n")
    f.close()
    return {'FINISHED'}

Blender 2.5 Python スクリプトによるエクスポータの作成 – マテリアルの出力 –


続いてマテリアルの出力することにします。マテリアルは “bpy.types.Object(ID)” の “active_material” で得ることが出来ます。後はいつもどおり、マニュアルを見ながら出力したいパラメータを出力していきます。

Material(ID)

ここまでのコードは以下のとおりです。

def write_some_data(context, filepath, use_some_setting):
    print("running write_some_data...")
    f = open(filepath, 'w')
    obj = bpy.context.selected_objects[0]
    mesh = obj.data
 
    f.write( "Model : \"%s\" {\n" % obj.name )
 
    # Material
    material = obj.active_material
    if material:
        f.write( "Material : \"%s\" {\n" % material.name )
        f.write( "Diffuse : { %f, %f, %f }\n" % ( material.diffuse_color.r, material.diffuse_color.g, material.diffuse_color.b ) )
        f.write( "Specular : { %f, %f, %f }\n" % ( material.specular_color.r, material.specular_color.g, material.specular_color.b ) )
        f.write( "Translucency : { %f }\n" % material.translucency )
        f.write( "Fresnel : { %f, %f }\n" % ( material.diffuse_fresnel, material.diffuse_fresnel_factor ) )
            f.write( "} // Material\n" )
 
    # Index
    f.write( "Faces : %d {\n" % len( mesh.faces ) )
    for face in mesh.faces:
        f.write( "%d { " % len( face.vertices ) )
        for index in face.vertices:
            f.write( "%d, " % index )
        f.write( "}\n" )
    f.write( "} // Faces\n" )
 
    # Vertex
    f.write( "Vertexes : %d {\n" % len( mesh.vertices ) )
    for vertex in mesh.vertices:
        f.write( "%d { %f, %f, %f }\n" % ( vertex.index, vertex.co.x, vertex.co.y, vertex.co.z ) )
    f.write( "} // Vertexes\n" )
 
    # Normals
    f.write( "Normals : %d {\n" % len( mesh.vertices ) )
    for vertex in mesh.vertices:
        f.write( "%d { %f, %f, %f }\n" % ( vertex.index, vertex.normal.x, vertex.normal.y, vertex.normal.z ) )
    f.write( "} // Normals\n" )    
 
    f.write( "} // Model\n")
    f.close()
    return {'FINISHED'}