# 共通：シーン初期化・カメラ・照明・レンダー設定
import bpy, math

def reset():
    bpy.ops.wm.read_factory_settings(use_empty=True)

def mat(name, color, rough=0.4, metal=0.0, sss=0.0):
    m = bpy.data.materials.new(name)
    m.use_nodes = True
    b = m.node_tree.nodes["Principled BSDF"]
    b.inputs["Base Color"].default_value = (*color, 1)
    b.inputs["Roughness"].default_value = rough
    b.inputs["Metallic"].default_value = metal
    if sss:
        b.inputs["Subsurface Weight"].default_value = sss
    return m

def stage(target=(0, 0, 0), cam_loc=(4, -4, 3), lens=50, floor_color=(0.85, 0.85, 0.82)):
    scn = bpy.context.scene
    # 床
    bpy.ops.mesh.primitive_plane_add(size=40, location=(0, 0, 0))
    bpy.context.object.data.materials.append(mat("floor", floor_color, rough=0.8))
    # カメラ（注視点を向く）
    bpy.ops.object.empty_add(location=target)
    tgt = bpy.context.object
    bpy.ops.object.camera_add(location=cam_loc)
    cam = bpy.context.object
    cam.data.lens = lens
    c = cam.constraints.new("TRACK_TO"); c.target = tgt
    scn.camera = cam
    # 照明：キー（面光源）＋フィル＋環境光
    bpy.ops.object.light_add(type="AREA", location=(3, -2, 5))
    key = bpy.context.object; key.data.energy = 600; key.data.size = 3
    key.rotation_euler = (math.radians(35), math.radians(25), math.radians(20))
    bpy.ops.object.light_add(type="AREA", location=(-4, -1, 3))
    fill = bpy.context.object; fill.data.energy = 150; fill.data.size = 4
    fill.rotation_euler = (math.radians(60), math.radians(-50), 0)
    w = bpy.data.worlds.new("w"); scn.world = w; w.use_nodes = True
    w.node_tree.nodes["Background"].inputs["Strength"].default_value = 0.4

def render(path, samples=96, res=(1200, 900)):
    scn = bpy.context.scene
    scn.render.engine = "CYCLES"
    prefs = bpy.context.preferences.addons["cycles"].preferences
    prefs.compute_device_type = "METAL"; prefs.get_devices()
    for d in prefs.devices: d.use = True
    scn.cycles.device = "GPU"
    scn.cycles.samples = samples
    scn.cycles.use_denoising = True
    scn.render.resolution_x, scn.render.resolution_y = res
    scn.render.filepath = path
    bpy.ops.render.render(write_still=True)
