Web Top Page
BlenderのPythonスクリプトで単色のベースカラーを設定する例

シェイダーエディターの接続リンクを作っているようなコードです。
set_rgbという関数で、第1引数のオブジェクトを、第2引数のRGB不透明度指定で、色を設定します。
なお、第3引数はマテリアルの名前です。(実行でOBJECTモードになります。)
import bpy
# 引数のオブジェクトにRGBの色を設定する(OBJECTモードに変わります)
def set_rgb(obj, rgb=(0.0, 0.0, 0.0, 1.0), materialname='マテリアル.01'):
bpy.ops.object.mode_set(mode='OBJECT')
obj=bpy.context.active_object # 直前でアクセスしたオブジェク
material = bpy.data.materials.new(materialname)# マテリアル生成
material.use_nodes = True
nodes = material.node_tree.nodes # ノードツリーを取得
links = material.node_tree.links
nodes.clear() # 既存ノードをクリア
#
bsdf = nodes.new(type='ShaderNodeBsdfPrincipled') # ノードを作成
bsdf.location = (0, 0)
material_output = nodes.new(type='ShaderNodeOutputMaterial')#シェーダーの最終出力を受け取るノード取得
material_output.location = (400, 0)
#
# Principled BSDF ノードの BSDF 出力を、Material Output ノードの Surface 入力に接続
links.new(bsdf.outputs['BSDF'], material_output.inputs['Surface'])# ノード間をリンク
#
if not bsdf.inputs['Base Color'].is_linked:
bsdf.inputs['Base Color'].default_value = rgb # Base Color を設定
if len(obj.data.materials) == 0:
obj.data.materials.append(material) # マテリアルがない場合は追加
else:
obj.data.materials[0] = material # 既存のマテリアルを置き換え
#
bpy.context.view_layer.update()# ビューポートを更新
bpy.ops.mesh.primitive_uv_sphere_add(radius=1, segments=8, ring_count=7, location=(-4.0, 0.0, 0.0) )
obj=bpy.context.active_object # 直前でアクセスしたオブジェク
set_rgb(obj, rgb=(0.0, 0.0, 1.0, 0.5), materialname='マテリアル青') # 青の半透明
上記は、objのオブジェクトでマテリアルを一旦クリアして一つのベースカラーを指定したマテリアルに作り直しています。
(一つのオブジェクトに複数のマテリアルを管理できますが、上記ではそれをクリアして、作り直しています。)
対して後述のset_basecolorは、既存のマテリアルのベースカラーを変更できます。
BlenderのPythonスクリプトで既存のマテリアルの単色のベースカラーを設定する。
(指定の名のマテリアルが存在しない場合、そのマテリアルを生成します。)
これを実現するset_basecolor関数を定義して利用しています。

第1引数のオブジェクトにおいて、第2引数の名前のマテリアルに第3引数のベースカラーを設定します。
以下では、UV球を生成した後にこの関数を利用て、'マテリアル.黒'と'マテリアル.白'のマテリアルを生成します。
(マティリアルプレビューにすると、先に設定した黒でレンダリングされます。)
その後に'EDIT'にして、Z軸で半径×0.8未満の面を選択状態にし、その選択面に'マテリアル.白'を割り当ていているコード例です。
# 引数のオブジェクトに、マテリアルのRGBの色を設定する(マテリアルが存在しない場合は生成する)
def set_basecolor(obj, materialname='マテリアル', rgb=(0.0, 0.0, 0.0, 1.0)):
idx=-1
for i in range(len(obj.data.materials)):# 既存のマテリアル検索
print(obj.data.materials[i].name)
if obj.data.materials[i].name.startswith(materialname):
idx = i
break
#
if idx!=-1:
material = obj.data.materials[idx]# マテリアル取得
for node in material.node_tree.nodes:
if node.type=='BSDF_PRINCIPLED':bsdf=node
if node.type=='OUTPUT_MATERIAL':material_output=node
print(f'ノード検索:{node}')
#
else:
print(f'{materialname}の名前でマテリアルの生成')
material = bpy.data.materials.new(materialname)# マテリアル生成
obj.data.materials.append(material) # マテリアルがない場合は追加
material.use_nodes = True
material.node_tree.nodes.clear()
bsdf = material.node_tree.nodes.new(type='ShaderNodeBsdfPrincipled') # Bsdfノードを作成
material_output = material.node_tree.nodes.new(type='ShaderNodeOutputMaterial')#シェーダーの最終出力を受け取るノード取得
bsdf.location = (0, 0)
material_output.location = (400, 0)
# Principled BSDF ノードの BSDF 出力を、Material Output ノードの Surface 入力に接続
material.node_tree.links.new(bsdf.outputs['BSDF'], material_output.inputs['Surface'])# ノード間をリンク
#
bsdf.inputs['Base Color'].default_value = rgb # Base Color を設定
bpy.context.view_layer.update()# ビューポートを更新
radius=0.01 # UV球半径
segments=16 # UV球の縦分割
ring_count=10 # UV球の角度分割
bpy.ops.mesh.primitive_uv_sphere_add(segments=segments, ring_count=ring_count, radius=radius)
bpy.ops.object.mode_set(mode='OBJECT')
eyeObj=bpy.context.active_object # 直前でアクセスしたオブジェク
set_basecolor(eyeObj, rgb=(0.0, 0.0, 0.0, 1.0), materialname='マテリアル.黒')
set_basecolor(eyeObj, rgb=(1.0, 1.0, 1.0, 1.0), materialname='マテリアル.白')
bpy.ops.object.mode_set(mode='EDIT')
import bmesh
bm = bmesh.from_edit_mesh(eyeObj.data) # 編集モード中のメッシュデータをBMeshに変換
for face in bm.faces: # 全ての面の走査
if face.calc_center_median().z < radius*0.8: face.select=True
else: face.select=False
bmesh.update_edit_mesh(eyeObj.data) # BMeshを更新(編集モードで、bmは引き続き編集可能)
bpy.context.object.active_material_index = 1 # 現在のマテリアルを1の指定('マテリアル.白')にする
bpy.ops.object.material_slot_assign()# 現在の選択面に選択のマテリアルを割り当て
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.transform.rotate(value=-1.5708, orient_axis='X') # X軸で、-90度を回転
bpy.types.Object を、他のオブジェクトのローカル座標へ移動する例
set_locationという関数を定義して実現する例です。
第1引数のオブジェクトを、第2引数のオブジェクトのローカル座標に移動する関数です
(第3引数が、第2引数のオブジェクトのローカル座標です。)
この例では移動対象のICO球を、トラース(ドーナツ型?)のローカル座標で、(0,0,0) の位置に移動しています。
なお、移動対象の球をスムーズシェードにして、ローカル座標を指定するトラースのオブジェクトをフラットシェードにして、
見栄えを区別しています。
import bpy
# move_objを、objのローカル座標で移動する。
def set_location(move_obj,obj, local_location=(0,0,0) ):
global_co = obj.matrix_world @ Vector(local_location)
move_obj.location=global_co # 位置変更
for obj in bpy.data.objects:# 'Camera' と 'Light' 以外を全て削除する
if obj.name=='Camera' or obj.name=='Light': continue
bpy.data.objects.remove( obj )
bpy.ops.mesh.primitive_torus_add(location=(-2, 1, 0.5), major_segments=8, minor_segments=4)
torus_obj=bpy.context.active_object # 直前でアクセスしたオブジェク
bpy.ops.object.shade_flat() # フラットシェード指定
bpy.ops.mesh.primitive_ico_sphere_add(radius=0.3)
sphere_obj=bpy.context.active_object # 直前でアクセスしたオブジェク
bpy.ops.object.shade_smooth()# スムーズシェード指定
set_location(move_obj=sphere_obj, obj=torus_obj, local_location=(0,0,0))