"""
タイトル: Blender 基本シーン設定スクリプト
var1.9.0 2024年11月19日
説明:シーン設定を効率化するスクリプト,処理を個別の関数に分割して再利用可能に設計されています。
"""
"""
以下読み込み方書式
import sys
import os
# スクリプトのあるディレクトリをPythonパスに追加
script_dir = os.path.dirname(bpy.data.filepath)
if script_dir not in sys.path:
sys.path.append(script_dir)
# インポート
from setup_stage import clear_stage,create_camera,create_light,set_background_color
"""
import bpy
import math
import mathutils
def clear_stage(keep_camera=True, keep_lights=True):
for obj in bpy.data.objects:
if (obj.type == 'CAMERA' and keep_camera) or (obj.type == 'LIGHT' and keep_lights):
continue
bpy.data.objects.remove(obj, do_unlink=True)
def clear_materials():
try:
for mat in bpy.data.materials:
bpy.data.materials.remove(mat, do_unlink=True)
print("すべてのマテリアルを削除しました。")
return True
except Exception as e:
print(f"マテリアル削除中にエラーが発生しました: {e}")
return False
def create_camera(location=(0, 0, 10), rotation=(math.radians(90), 0, 0), name="Camera"):
bpy.ops.object.camera_add(location=location)
camera = bpy.context.object
camera.name = name
camera.rotation_euler = rotation
return camera
def point_camera(camera, target=None, target_location=None):
"""
Args:
camera (bpy.types.Object): カメラオブジェクト。
target (bpy.types.Object): カメラが向く対象のオブジェクト(指定しない場合は target_location を使用)。
target_location (tuple): カメラが向く座標 (x, y, z)。target が None の場合に有効。
Returns:
bool: 成功した場合は True、失敗した場合は False。
"""
try:
if target is not None:
target_location = target.matrix_world.translation
elif target_location is None:
raise ValueError("target または target_location のいずれかを指定する必要があります。")
camera_location = camera.matrix_world.translation
direction = camera_location -mathutils.Vector(target_location)
direction.normalize()
rotation = direction.to_track_quat('Z', 'Y').to_euler()
camera.rotation_euler = rotation
return True
except Exception as e:
print(f"カメラの向き変更中にエラーが発生しました: {e}")
return False
def create_light(location=(10, 10, 10), rotation=(math.radians(0), math.radians(45), 0), light_type='SUN', energy=1000, color=(1.0, 1.0, 1.0), name="Light"):
bpy.ops.object.light_add(type=light_type, location=location)
light = bpy.context.object
light.name = name
light.rotation_euler = rotation
light.data.energy = energy
light.data.color = color
return light
def point_light(light_object, target_location):
try:
if light_object.type != 'LIGHT':
raise ValueError(f"Object '{light_object.name}' is not a light.")
light_location = mathutils.Vector(light_object.location)
direction = mathutils.Vector(target_location) - light_location
rotation = direction.to_track_quat('-Z', 'Y').to_euler()
light_object.rotation_euler = rotation
return True
except Exception as e:
print(f"照明の向き変更中にエラーが発生しました: {e}")
return False
def set_background_color(color=(0.0, 0.0, 0.0, 1.0)):
bpy.context.scene.world.use_nodes = True
bg_node = bpy.context.scene.world.node_tree.nodes.get("Background")
if bg_node:
bg_node.inputs[0].default_value = color
return True
else:
print("背景ノードが見つかりません。スキップします。")
return False
def initialize_stage(
camera_location=(0, 10, 10),
camera_rotation=(math.radians(45), math.radians(0), math.radians(180)),
light_location=(5, 5, 5),
light_rotation=(math.radians(-45), math.radians(0), 0),
light_type='SUN',
light_energy=5,
light_color=(1.0, 1.0, 1.0),
background_color=(0.0, 0.0, 0.5, 1.0),
keep_camera=False,
keep_lights=False,
keep_matelials=True):
clear_stage(keep_camera=keep_camera, keep_lights=keep_lights)
if keep_matelials:
clear_materials()
camera = create_camera(location=camera_location, rotation=camera_rotation, name="Camera")
light = create_light(location=light_location, rotation=light_rotation, light_type=light_type, color=light_color, energy=light_energy, name="Light")
set_background_color(color=background_color)
return camera,light
def create_material(
name="Material",
color=(1.0, 1.0, 1.0, 1.0),
specular=0.5,
roughness=0.5,
metallic=0.0,
emission_color=(0.0, 0.0, 0.0, 1.0),
emission_strength=0.0, alpha=1.0, use_alpha=False):
"""
多機能マテリアル生成関数。
Args:
name (str): マテリアル名。
color (tuple): ベースカラー (R, G, B, A)。
specular (float): 反射強度 (0.0 - 1.0)。
roughness (float): 表面の粗さ (0.0 - 1.0)。
metallic (float): 金属度 (0.0 - 1.0)。
emission_color (tuple): 発光色 (R, G, B, A)。
emission_strength (float): 発光の強度。
alpha (float): 透明度 (0.0 - 1.0)。
use_alpha (bool): 透明度を有効にするかどうか。
Returns:
bpy.types.Material: 作成されたマテリアルオブジェクト。
"""
mat = bpy.data.materials.get(name)
if not mat:
mat = bpy.data.materials.new(name=name)
mat.use_nodes = True
bsdf = mat.node_tree.nodes.get("Principled BSDF")
if bsdf:
if "Base Color" in bsdf.inputs:
bsdf.inputs["Base Color"].default_value = color
if "Specular" in bsdf.inputs:
bsdf.inputs["Specular"].default_value = specular
if "Roughness" in bsdf.inputs:
bsdf.inputs["Roughness"].default_value = roughness
if "Metallic" in bsdf.inputs:
bsdf.inputs["Metallic"].default_value = metallic
if emission_strength > 0.0 and "Emission" in bsdf.inputs:
bsdf.inputs["Emission"].default_value = emission_color
if "Emission Strength" in bsdf.inputs:
bsdf.inputs["Emission Strength"].default_value = emission_strength
if use_alpha and "Alpha" in bsdf.inputs:
bsdf.inputs["Alpha"].default_value = alpha
mat.blend_method = 'BLEND'
mat.shadow_method = 'HASHED'
return mat
def create_primitive_object(
object_type='SPHERE',
location=(0, 0, 0),
scale=(1, 1, 1),
rotation=(0, 0, 0),
material=None,
name="Object",
smooth=False,
**kwargs):
"""
高機能プリミティブオブジェクト生成関数。
Args:
object_type (str): 作成するプリミティブオブジェクトのタイプ。
サポートされるタイプ: 'SPHERE', 'CUBE', 'CYLINDER', 'CONE', 'PLANE', 'ICO_SPHERE', 'MONKEY'。
location (tuple): 生成するオブジェクトの座標。
scale (tuple): オブジェクトのスケール。
rotation (tuple): オブジェクトの回転 (radians)。
material (bpy.types.Material): 適用するマテリアル。指定がない場合は新規作成。
name (str): オブジェクトの名前。
smooth (bool): スムースシェーディングを適用するかどうか。
kwargs: オブジェクト固有のオプション(ポリゴン数など)。
- 'segments' (int): 球体、円柱、円錐のセグメント数。
- 'ring_count' (int): UV球体のリング数。
- 'subdivisions' (int): ICO球体の分割数。
Returns:
bpy.types.Object: 作成されたオブジェクト。
"""
obj = None
if object_type.upper() == 'SPHERE':
segments = kwargs.get('segments', 32)
ring_count = kwargs.get('ring_count', 16)
bpy.ops.mesh.primitive_uv_sphere_add(location=location, segments=segments, ring_count=ring_count)
obj = bpy.context.object
elif object_type.upper() == 'CUBE':
bpy.ops.mesh.primitive_cube_add(location=location)
obj = bpy.context.object
elif object_type.upper() == 'CYLINDER':
segments = kwargs.get('segments', 32)
bpy.ops.mesh.primitive_cylinder_add(location=location, vertices=segments)
obj = bpy.context.object
elif object_type.upper() == 'CONE':
segments = kwargs.get('segments', 32)
bpy.ops.mesh.primitive_cone_add(location=location, vertices=segments)
obj = bpy.context.object
elif object_type.upper() == 'PLANE':
bpy.ops.mesh.primitive_plane_add(location=location)
obj = bpy.context.object
elif object_type.upper() == 'ICO_SPHERE':
subdivisions = kwargs.get('subdivisions', 2)
bpy.ops.mesh.primitive_ico_sphere_add(location=location, subdivisions=subdivisions)
obj = bpy.context.object
elif object_type.upper() == 'MONKEY':
bpy.ops.mesh.primitive_monkey_add(location=location)
obj = bpy.context.object
else:
raise ValueError(f"Unsupported object type: {object_type}")
if obj:
obj.name = name
obj.scale = scale
obj.rotation_euler = rotation
if material is None:
material = create_material(name=f"{name}_Material")
if material:
obj.data.materials.append(material)
if smooth:
bpy.ops.object.shade_smooth()
else:
bpy.ops.object.shade_flat()
return obj
if __name__ == "__main__":
camera, light = initialize_stage(
camera_location=(20, 10, 10),
camera_rotation=(math.radians(90), 0, 0),
light_location=(0, 10, 10),
light_type='SPOT',
light_energy=5000,
light_color=(1.0, 1.0, 0.3),
background_color=(0.0, 0.3, 0.8, 1.0),
keep_camera=False,
keep_lights=False,
keep_matelials=True
)
target_location = (0, 0, 0)
point_camera(camera, target_location=(0, -1, 0))
point_light(light, target_location)
plane_material = create_material(name="PlaneMaterial", color=(0.5, 0.5, 0.5, 1))
red_material = create_material(name="RedMaterial", color=(1.0, 0.0, 0.0, 1.0))
blue_material = create_material(name="BlueMaterial", color=(0.0, 0.0, 1.0, 1.0))
create_primitive_object(object_type='SPHERE', location=(0, 0, 0), scale=(1, 1, 1), material=red_material, name="RedSphere", smooth=True)
create_primitive_object(object_type='CUBE', location=(2, 2, 0), scale=(1, 1, 1), material=blue_material, name="BlueCube")
create_primitive_object(object_type='PLANE', location=(0, 0, -1), scale=(10, 10, 1), material=plane_material, name="Floor")