bpy(Blender Python API)を用いてテキストベースでマテリアルの追加、割り当て、複製操作についてまとめておきます。
前提としてマテリアルノードを使用する方針とします。以下マテリアルノードの作業イメージです。
動作確認環境 : Blender 4.2
マテリアルの新規追加
オブジェクトに対して新規マテリアルを作成して、割り当てます。
- オブジェクトを選択(アクティブ化)
- マテリアルの追加
Python :
def add_new_material(
material_name="Base_Material_Name"
):
# 新しいマテリアルを作成
new_material = bpy.data.materials.new(name="Material.001")
# ノードを使用する設定にする
new_material.use_nodes = True
# マテリアルの名前を変更
new_material.name = material_name
# オブジェクトに新しいマテリアルを割り当てる
obj = bpy.context.object
# 新しいマテリアルを追加
obj.data.materials.append(new_material)
# 名前でマテリアルスロットをアクティブにする
for i, mat in enumerate(obj.material_slots):
if mat.material.name == material_name:
obj.active_material_index = i
break
# Assign
bpy.ops.object.material_slot_assign()
05行目でマテリアルを作成し、オブジェクトにマテリアル割り当て、マテリアルスロットのアクティブ化、アサインまでの行程を関数でひとまとめにしています。
使用例は、こちら(本記事下)にあります。
既存マテリアル割り当て
すでに存在するマテリアルをオブジェクトに割り当てます。
複数のオブジェクトに対して同じマテリアルを割り当てる場合に有効です。
- オブジェクトの選択(アクティブ化)
- 既存マテリアルの割り当て
Python :
def allocate_material(
material_name="Base_Material_Name"
):
# マテリアル取得
material = bpy.data.materials.get(material_name)
# ノードを使用する設定にする
material.use_nodes = True
if material is None:
print(f"Material '{material_name}' not found.")
else:
# マテリアルスロットがない場合、新しいスロットを追加して割り当て
bpy.context.active_object.data.materials.append(material)
# 名前でマテリアルスロットをアクティブにする
for i, mat in enumerate(bpy.context.active_object.material_slots):
if mat.material.name == material_name:
bpy.context.active_object.active_material_index = i
break
# Assign
bpy.ops.object.material_slot_assign()
02行目 :
引数としてマテリアルの名前を指定して、すでに存在するマテリアルを選択したオブジェクトに対して割り当てます。
1つのマテリアルの設定を変更すると、この処理で割り当てるすべてのオブジェクトに対して影響があります。
使用例は、こちら(本記事下)にあります。
マテリアルの複製・コピー
既存のマテリアルを複製した、新規マテリアルを作成します。
上の割り当てとは違い、元のマテリアルを変更しても複製先のマテリアルに影響はありません。
Python :
def cp_exist_material(
exist_material_name="exist_material_name"
, new_material_name="new_material_name"
):
# マテリアル取得
material = bpy.data.materials.get(exist_material_name)
# 新しいマテリアル名を付けて、マテリアルをオブジェクトに割り当て
new_material = material.copy()
new_material.name = new_material_name
# マテリアル割り当て
bpy.context.active_object.data.materials.append(new_material)
# 名前でマテリアルスロットをアクティブにする
for i, mat in enumerate(bpy.context.active_object.material_slots):
if mat.material.name == new_material_name:
bpy.context.active_object.active_material_index = i
break
# スロット割り当て
bpy.ops.object.material_slot_assign()
02, 03行目で引数として、
- 既存のマテリアル名
- 新規作成するマテリアル名
元のマテリアルに変更を加えても複製先のマテリアルに影響はありませんが、テキストベースでマテリアル操作を記載している場合、コピー元のマテリアル側のソースを変更すると、後段の複製処理に影響しますので注意が必要です。
使用例は以下です。
基本マテリアル操作実装使用例
最後に上記のマテリアル操作を用いた簡単なデモを示します。
実装は以下のような処理になります。
- オブジェクト追加
- マテリアル新規追加 / 色の変更
- オブジェクト追加
- マテリアルの複製 / 色の変更
- オブジェクト追加
- 2で作成したマテリアル割り当て
の順で下の立方体からオブジェクトの設定、マテリアル適用を行っています。
Python :
def Base_create():
bpy.ops.object.mode_set(mode='OBJECT')
# 立方体を追加
bpy.ops.mesh.primitive_cube_add(
size=1
, location=(0, 0, 1)
, scale=(1,1,1)
)
# 名前設定
bpy.context.object.name = "cube_00"
# マテリアル追加
add_new_material(material_name="MT_cube_00")
# ノード 値変更
node_value_change(
material_name="MT_cube_00"
, node_name="Principled BSDF"
, element_name="Base Color"
, set_value=(
0.100 # red
, 0.700 # green
, 0.900 # blue
, 1 # alpha
)
)
# 立方体を追加
bpy.ops.mesh.primitive_cube_add(
size=1
, location=(0, 0, 1.75)
, scale=(0.5,0.5,0.5)
)
# 名前設定
bpy.context.object.name = "cube_01"
# マテリアルコピー/割り当て
cp_exist_material(
exist_material_name="MT_cube_00"
, new_material_name="MT_cube_01"
)
# ノード 値変更
node_value_change(
material_name="MT_cube_01"
, node_name="Principled BSDF"
, element_name="Base Color"
, set_value=(
0.900 # red
, 0.200 # green
, 0.100 # blue
, 1 # alpha
)
)
# 立方体を追加
bpy.ops.mesh.primitive_cube_add(
size=1
, location=(0, 0, 2.125)
, scale=(0.25,0.25,0.25)
)
# 名前設定
bpy.context.object.name = "cube_02"
# 既存マテリアル割り当て
allocate_material(material_name="MT_cube_00")
Base_create()
▼node_value_change
以上