メッシュの押し出し【第 12 回 Python × Blender】
今日はメッシュの押し出し(extrude)について書きたいと思います。
今回のサンプルスクリプトは、正十二面体の面のいくつかを、その面の法線方向に押し出す Python スクリプトです。
import bpy import bmesh '''オブジェクトモードから始める必要がある.''' # オブジェクトモードに変更. bpy.ops.object.mode_set(mode='OBJECT') # 全てのオブジェクトを選択. bpy.ops.object.select_all(action='SELECT') # 選択された全てのオブジェクトを削除. bpy.ops.object.delete() # 立方体オブジェクトを配置. bpy.ops.mesh.primitive_cube_add(radius=0.5, location=(0, 0, 0)) # 編集モードに切り替え. bpy.ops.object.mode_set(mode='EDIT') '''立方体の面を全て押し出す.''' # 見易さのために面モード(Face Mode)に切り替え. bpy.ops.mesh.select_mode(type="FACE") # bmesh オブジェクトのインスタンス化. cube_bmesh = bmesh.from_edit_mesh(bpy.context.object.data) # 立方体の面数(6 面)分ループ処理. for i in range(6): # 全ての頂点・辺・面を非選択状態にする. bpy.ops.mesh.select_all(action='DESELECT') # 面番号 i の面を選択. cube_bmesh.faces.ensure_lookup_table() cube_bmesh.faces[i].select = True # 面番号 0 の面を法線方向に 1 押し出す. bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value": (0, 0, 1), "constraint_axis": (True, True, True),"constraint_orientation": 'NORMAL'}) # 最後にもう一度押し出す. bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value": (0, 0, 1), "constraint_axis": (True, True, True),"constraint_orientation": 'NORMAL'})
実行結果は以下のようになるはずです。
上記プログラムを見ると、bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value": (0, 0, 1), "constraint_axis": (True, True, True),"constraint_orientation": 'NORMAL'})
によって選択状態にある面が法線方向に 1 ずらされているのが分かります。
立方体ではなく、正十二面体で遊んでみるとこうなります。
import bpy import bmesh import math '''数学定数.''' # 黄金比. Phi = (1 + math.sqrt(5)) / 2 '''正十二面体を配置する関数.''' def dodecahedron_add(name, location=(0, 0, 0)): # 正十二面体の頂点リスト. 座標で定義し, 頂点番号はリストインデックスと一致. verts = [(1 / Phi, 0, Phi), (-1 / Phi, 0, Phi), (1, 1, 1), (-1, 1, 1), (-1, -1, 1), (1, -1, 1), (0, Phi, 1 / Phi), (0, -Phi, 1 / Phi), (Phi, 1 / Phi, 0), (-Phi, 1 / Phi, 0), (-Phi, -1 / Phi, 0), (Phi, -1 / Phi, 0), (0, Phi, -1 / Phi), (0, -Phi, -1 / Phi), (1, 1, -1), (-1, 1, -1), (-1, -1, -1), (1, -1, -1), (1 / Phi, 0, -Phi), (-1 / Phi, 0, -Phi)] # 正二十面体の面リスト. faces = [(0, 2, 6, 3, 1), (0, 1, 4, 7, 5), (0, 5, 11, 8, 2), (2, 8, 14, 12, 6), (3, 6, 12, 15, 9),(1, 3, 9, 10, 4), (4, 10, 16, 13, 7), (5, 7, 13, 17, 11), (8, 11, 17, 18, 14), (12, 14, 18, 19, 15), (9, 15, 19, 16, 10), (13, 16, 19, 18, 17)] # 正十二面体メッシュの定義. meshes = bpy.data.meshes.new(name) # 正十二面体オブジェクトの定義. dodecahedron = bpy.data.objects.new(name, meshes) # 正十二面体オブジェクトの位置を宣言. dodecahedron.location = location # scene に正十二面体オブジェクトを追加. bpy.context.scene.objects.link(dodecahedron) # メッシュを生成. meshes.from_pydata(verts, [], faces) # 正十二面体の辺を生成. meshes.update(calc_edges=True) # 正十二面体オブジェクトをアクティブ化. bpy.context.scene.objects.active = bpy.data.objects[name] '''scene が empty であるとき, スクリプトは動かないのでオブジェクトモードから始める必要がある.''' # オブジェクトモードに変更. bpy.ops.object.mode_set(mode='OBJECT') # 全てのオブジェクトを選択. bpy.ops.object.select_all(action='SELECT') # 選択された全てのオブジェクトを削除. bpy.ops.object.delete() # 正十二面体オブジェクトを配置. dodecahedron_add(name="Dodeca.1") # 編集モードに切り替え. bpy.ops.object.mode_set(mode='EDIT') '''正十二面体オブジェクトの頂点・辺・面の選択.''' # 見易さのために面モード(Face Mode)に切り替え. bpy.ops.mesh.select_mode(type="FACE") # bmesh オブジェクトのインスタンス化. dodeca_bmesh = bmesh.from_edit_mesh(bpy.context.object.data) # 正十二面体の面数(12 面)分ループ処理. for i in range(12): # 全ての頂点・辺・面を非選択状態にする. bpy.ops.mesh.select_all(action='DESELECT') # 面番号 i の面を選択. dodeca_bmesh.faces.ensure_lookup_table() dodeca_bmesh.faces[i].select = True # 面番号 i の面を適当に押し出す. bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value": (0, 0, 1), "constraint_axis": (True, True, True),"constraint_orientation": 'NORMAL'}) bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value": (0.5, 0, 1), "constraint_axis": (True, True, True),"constraint_orientation": 'NORMAL'}) bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value": (-0.5, 0, 1), "constraint_axis": (True, True, True),"constraint_orientation": 'NORMAL'})
実行結果は以下のようになるはずです。
う〜ん、サンゴみたい🐟