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)