diff --git a/gravity_simulation_ui.py b/gravity_simulation_ui.py new file mode 100644 index 0000000..ec09ecc --- /dev/null +++ b/gravity_simulation_ui.py @@ -0,0 +1,103 @@ +import bpy +import numpy as np + +# UIプロパティ登録 +def register_props(): + bpy.types.Scene.gravity_strength = bpy.props.FloatProperty( + name="重力定数 G", + default=1.0, + min=0.1, + max=5.0, + step=0.1, + precision=2 + ) + +# 軌道シミュレーション実行関数 +def calculate_orbit(context): + G = context.scene.gravity_strength + M = 1000 + pos = np.array([5.0, 0.0]) # 初期位置(固定) + vel = np.array([0.0, 10.0]) # 初期速度(固定) + dt = 0.01 + steps = 400 + positions = [] + + # 既存オブジェクト削除 + bpy.ops.object.select_all(action='SELECT') + bpy.ops.object.delete(use_global=False) + + # 太陽(オレンジ) + bpy.ops.mesh.primitive_uv_sphere_add(radius=1, location=(0, 0, 0)) + sun = bpy.context.object + sun.name = "Sun" + mat = bpy.data.materials.new("SunMat") + mat.diffuse_color = (1.0, 0.5, 0.0, 1) + sun.data.materials.append(mat) + + # 地球(青) + bpy.ops.mesh.primitive_uv_sphere_add(radius=0.3, location=(pos[0], pos[1], 0)) + earth = bpy.context.object + earth.name = "Earth" + mat = bpy.data.materials.new("EarthMat") + mat.diffuse_color = (0.2, 0.5, 1.0, 1) + earth.data.materials.append(mat) + + for _ in range(steps): + r_vec = -pos + dist = np.linalg.norm(r_vec) + acc = G * M * r_vec / dist**3 + vel += acc * dt + pos += vel * dt + positions.append(pos.copy()) + + # アニメーション設定 + scene = context.scene + scene.frame_start = 1 + scene.frame_end = steps + frame = 1 + for p in positions: + earth.location = (p[0], p[1], 0) + earth.keyframe_insert(data_path="location", frame=frame) + frame += 1 + +# UIパネル +class GravityOnlyPanel(bpy.types.Panel): + bl_label = "重力定数で軌道観察" + bl_idname = "VIEW3D_PT_gravity_only" + bl_space_type = 'VIEW_3D' + bl_region_type = 'UI' + bl_category = 'OrbitSim' + + def draw(self, context): + layout = self.layout + layout.prop(context.scene, "gravity_strength") + layout.operator("orbit.recalc", text="再計算") + layout.operator("screen.animation_play", text="▶ アニメ再生") + +# 再計算ボタン +class RecalcOrbitOperator(bpy.types.Operator): + bl_idname = "orbit.recalc" + bl_label = "軌道を再計算" + + def execute(self, context): + calculate_orbit(context) + self.report({'INFO'}, "軌道を再計算しました") + return {'FINISHED'} + +# 登録と解除 +classes = [GravityOnlyPanel, RecalcOrbitOperator] + +def register(): + for cls in classes: + bpy.utils.register_class(cls) + register_props() + +def unregister(): + for cls in reversed(classes): + bpy.utils.unregister_class(cls) + del bpy.types.Scene.gravity_strength + +# 登録して初回計算を自動実行 +if __name__ == "__main__": + register() + calculate_orbit(bpy.context) \ No newline at end of file