Newer
Older
InforSystem / blend / simulation.py
import bpy
import numpy as np
import math

# 設定:スケール・パス
AU = 20.0
earth_radius = 0.3
sun_radius = 5.0
moon_radius = 0.08
moon_distance = 0.7

G = 1.0
M = 1000
dt = 0.01
steps = 400

# 画像ファイル
earth_image_path = "earth_texture.jpg"
sun_image_path   = "sun_texture.jpg"
moon_image_path  = "moon_texture.jpg"

# 初期化:全削除・背景黒
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)

bg = bpy.data.worlds["World"].node_tree.nodes.get("Background")
if bg:
    bg.inputs[0].default_value = (0, 0, 0, 1)

# 関数:画像テクスチャを貼る
def apply_texture(obj, image_path):
    mat = bpy.data.materials.new(name=obj.name + "_Mat")
    mat.use_nodes = True
    nodes = mat.node_tree.nodes
    links = mat.node_tree.links

    bsdf = nodes.get("Principled BSDF")
    tex_image = nodes.new(type='ShaderNodeTexImage')
    img = bpy.data.images.load(image_path)
    tex_image.image = img
    links.new(tex_image.outputs['Color'], bsdf.inputs['Base Color'])

    obj.data.materials.clear()
    obj.data.materials.append(mat)

# 太陽(自転+テクスチャ)
bpy.ops.mesh.primitive_uv_sphere_add(radius=sun_radius, location=(0, 0, 0))
sun = bpy.context.object
sun.name = "Sun"
apply_texture(sun, sun_image_path)

# ==========================================
# 地球(公転・自転+テクスチャ)
# ==========================================
pos = np.array([AU, 0.0])
vel = np.array([0.0, 7.07])  # √(GM/r) = √(1000/20)
bpy.ops.mesh.primitive_uv_sphere_add(radius=earth_radius, location=(pos[0], pos[1], 0))
earth = bpy.context.object
earth.name = "Earth"
apply_texture(earth, earth_image_path)

# ==========================================
# 月(地球周囲を公転・自転+テクスチャ)
# ==========================================
bpy.ops.mesh.primitive_uv_sphere_add(radius=moon_radius, location=(pos[0] + moon_distance, pos[1], 0))
moon = bpy.context.object
moon.name = "Moon"
apply_texture(moon, moon_image_path)

# ==========================================
# カメラとライト
# ==========================================
bpy.ops.object.camera_add(location=(70, -70, 40), rotation=(math.radians(60), 0, math.radians(45)))
bpy.context.scene.camera = bpy.context.object

light_data = bpy.data.lights.new(name="SunLight", type='SUN')
light = bpy.data.objects.new(name="SunLight", object_data=light_data)
bpy.context.collection.objects.link(light)
light.location = (0, 0, 0)

# ==========================================
# アニメーション処理
# ==========================================
scene = bpy.context.scene
scene.frame_start = 1
scene.frame_end = steps

sun_rot = 0.0
earth_rot = 0.0
moon_rot = 0.0
moon_angle = 0.0
moon_speed = 2 * math.pi / 50  # 月の1公転 = 50フレーム

for frame in range(1, steps + 1):
    # 地球の公転
    r_vec = -pos
    dist = np.linalg.norm(r_vec)
    acc = G * M * r_vec / dist**3
    vel += acc * dt
    pos += vel * dt

    # 自転更新
    sun_rot += 2 * math.pi / 300
    earth_rot += 2 * math.pi / 50
    moon_rot += 2 * math.pi / 50

    # 地球:位置・回転
    earth.location = (pos[0], pos[1], 0)
    earth.rotation_euler = (0, 0, earth_rot)
    earth.keyframe_insert(data_path="location", frame=frame)
    earth.keyframe_insert(data_path="rotation_euler", frame=frame)

    # 月:地球の周囲を回る + 自転
    moon_angle += moon_speed
    moon.location = (
        pos[0] + moon_distance * math.cos(moon_angle),
        pos[1] + moon_distance * math.sin(moon_angle),
        0
    )
    moon.rotation_euler = (0, 0, moon_rot)
    moon.keyframe_insert(data_path="location", frame=frame)
    moon.keyframe_insert(data_path="rotation_euler", frame=frame)

    # 太陽の自転
    sun.rotation_euler = (0, 0, sun_rot)
    sun.keyframe_insert(data_path="rotation_euler", frame=frame)