diff --git a/objs/halley_comet.py b/objs/halley_comet.py new file mode 100644 index 0000000000000000000000000000000000000000..d2164e15a8fc408706562bb4d9ac3b1a0733ffcd --- /dev/null +++ b/objs/halley_comet.py @@ -0,0 +1,115 @@ +# -*- coding:utf-8 -*- +# title :水滴 +# description :水滴 +# author :Python超人 +# date :2023-08-02 +# link :https://gitcode.net/pythoncr/ +# python_version :3.8 +# ============================================================================== +from objs.obj import Obj + + +class HalleComet(Obj): + """ + 哈雷彗星 + 来源:https://www.cgmodel.com/model/500318.html + """ + + def __init__(self, name="哈雷彗星", mass=5.97237e24, + init_position=[0, 0, 0], + init_velocity=[0, 0, 0], + texture="drops.png", size_scale=1.0, distance_scale=1.0, + ignore_mass=False, density=1e3, color=(7, 0, 162), + trail_color=None, show_name=False, + model="drops.obj", rotation=(0, 0, 0), + parent=None, gravity_only_for=[]): + params = { + "name": name, + "mass": mass, + "init_position": init_position, + "init_velocity": init_velocity, + "density": density, + "color": color, + "texture": texture, + "size_scale": size_scale, + "distance_scale": distance_scale, + "ignore_mass": ignore_mass, + "trail_color": trail_color, + "show_name": show_name, + "parent": parent, + "rotation": rotation, + "gravity_only_for": gravity_only_for, + "model": model + } + super().__init__(**params) + + +from ursina.prefabs.primitives import Shader + +matcap_shader = Shader(name='matcap_shader', language=Shader.GLSL, vertex='''#version 140 +uniform mat4 p3d_ModelViewProjectionMatrix; +uniform mat4 p3d_ModelMatrix; +uniform mat4 p3d_ModelViewMatrix; +uniform mat3 p3d_NormalMatrix; +in vec4 p3d_Vertex; +in vec3 p3d_Normal; + +out vec3 eye; +out vec3 view_normal; +// reflect alternative: +// r = e - 2. * dot( n, e ) * n; + +void main() { + gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex; + + eye = normalize(vec3(p3d_ModelViewMatrix * vec4(p3d_Vertex.xyz, 1.0))); + view_normal = normalize( p3d_NormalMatrix * p3d_Normal ); +} +''', + fragment=''' +#version 130 +uniform sampler2D p3d_Texture0; +uniform vec4 p3d_ColorScale; + +in vec3 eye; +in vec3 view_normal; +out vec4 fragColor; + +void main() { + + vec3 r = reflect( eye, view_normal ); + float m = 2. * sqrt( pow( r.x, 2. ) + pow( r.y, 2. ) + pow( r.z + 1., 2. ) ); + vec2 vN = r.xy / m + .5; + + vec3 base = texture2D( p3d_Texture0, vN ).rgb; + // vec3 base = texture2D( p3d_Texture0, uv ).rgb; + fragColor = vec4( base, 1. ) * p3d_ColorScale; +} + +''', + ) + +if __name__ == '__main__': + shader = matcap_shader + + halle_comet = HalleComet( + # texture="drops_normal.png" + # texture="drops_uvw.png" + texture="drops.png" + ) + halle_comet.init_velocity = [0, 0, -10] + print(halle_comet) + + + def on_ready(): + halle_comet.planet.rotation_x = 90 + halle_comet.planet.shader = shader, + halle_comet.planet.init_scale = halle_comet.planet.scale_x * 2 + # halle_comet.planet.init_update = halle_comet.planet.update + + def on_timer_changed(time_data): + # halle_comet.planet.init_update = body.planet.update + halle_comet.planet.scale_z = halle_comet.planet.init_scale + + + halle_comet.show_demo(size_scale=1000000, on_ready_fun=on_ready, on_timer_changed_fun=on_timer_changed) diff --git a/objs/obj.py b/objs/obj.py index 6614e03a2e9e4e3fdf1c89b422f8e51e5a6b072f..6ff9a53a649614730bcddcfd0e55a088d77ffd3c 100644 --- a/objs/obj.py +++ b/objs/obj.py @@ -482,7 +482,7 @@ class Obj(metaclass=ABCMeta): return body_data - def show_demo(self, size_scale=10000, on_ready_fun=None): + def show_demo(self, size_scale=10000, on_ready_fun=None, on_timer_changed_fun=None): from sim_scenes.func import ursina_run from sim_scenes.func import camera_look_at from simulators.ursina.ursina_event import UrsinaEvent @@ -496,8 +496,16 @@ class Obj(metaclass=ABCMeta): if callable(on_ready_fun): on_ready_fun() + def on_timer_changed(time_data): + if callable(on_timer_changed_fun): + on_timer_changed_fun(time_data) + # 运行前会触发 on_ready - UrsinaEvent.on_ready_subscription(on_ready) + if on_ready_fun is not None: + UrsinaEvent.on_ready_subscription(on_ready) + + if on_timer_changed_fun is not None: + UrsinaEvent.on_timer_changed_subscription(on_timer_changed) ursina_run(bodies=[self], position=(0, 3000000, -9000000)) diff --git a/sim_scenes/solar_system/halley_comet.py b/sim_scenes/solar_system/halley_comet.py new file mode 100644 index 0000000000000000000000000000000000000000..9b20d1c585586f16017ba8a03612f6039e783035 --- /dev/null +++ b/sim_scenes/solar_system/halley_comet.py @@ -0,0 +1,119 @@ +# -*- coding:utf-8 -*- +# title :哈雷彗星场景模拟 +# description :哈雷彗星场景模拟 +# author :Python超人 +# date :2023-10-25 +# link :https://gitcode.net/pythoncr/ +# python_version :3.9 +# ============================================================================== +import time + +from ursina import camera, application + +from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto +from common.celestial_data_service import get_init_pos_vels, init_bodies_pos_vels +from common.consts import SECONDS_PER_WEEK, AU +from objs import QuadObj, CircleObj, Obj +from sim_scenes.func import camera_look_at, two_bodies_colliding +from sim_scenes.func import ursina_run, create_sphere_sky +from simulators.ursina.ursina_event import UrsinaEvent + + +class HalleyCometSim: + """ + 哈雷彗星场景模拟 + """ + + def __init__(self): + pass + + def build_solar_system(self): + # region 构建太阳系 + self.sun = Sun(size_scale=0.8e2) + self.bodies = [ + self.sun, # 太阳放大 80 倍 + Mercury(size_scale=4e3, distance_scale=1.3), # 水星放大 4000 倍,距离放大 1.3 倍 + Venus(size_scale=4e3, distance_scale=1.3), # 金星放大 4000 倍,距离放大 1.3 倍 + Earth(size_scale=4e3, distance_scale=1.3, rotate_angle=0), # 地球放大 4000 倍,距离放大 1.3 倍 + Mars(size_scale=4e3, distance_scale=1.2), # 火星放大 4000 倍,距离放大 1.2 倍 + Jupiter(size_scale=0.68e3, distance_scale=0.72), # 木星放大 680 倍,距离缩小到真实距离的 0.72 + Saturn(size_scale=0.68e3, distance_scale=0.52), # 土星放大 680 倍,距离缩小到真实距离的 0.52 + Uranus(size_scale=1.5e3, distance_scale=0.36), # 天王星放大 1500 倍,距离缩小到真实距离的 0.36 + Neptune(size_scale=1.5e3, distance_scale=0.27), # 海王星放大 1500 倍,距离缩小到真实距离的 0.27 + Pluto(size_scale=10e3, distance_scale=0.23), # 冥王星放大 10000 倍,距离缩小到真实距离的 0.23(从太阳系的行星中排除) + ] + # endregion + + init_bodies_pos_vels(self.bodies) + + def build_halley_comet(self): + """ + 创建哈雷彗星 + @return: + """ + self.halley_comet = QuadObj(texture='two_way_foil.png', + # size_scale=4e7, + size_scale=1e7, + init_velocity=[20, -6, 150], + init_position=[0, 0.5 * AU, -10 * AU]) \ + .set_light_disable(True) + + self.bodies.append(self.halley_comet) + + + def build(self): + self.build_solar_system() + self.build_halley_comet() + + def on_ready(self): + """ + 事件绑定后,模拟器运行前会触发 + @return: + """ + # 创建天空 + # camera.clip_plane_near = 0.1 + camera.clip_plane_far = 1000000 + create_sphere_sky(scale=200000) + application.time_scale = 5 + + + + def on_timer_changed(self, time_data): + """ + + @param time_data: + @return: + """ + # 原始方形二向箔飞行的翻转效果 + if self.halley_comet.planet.enabled: + self.halley_comet.planet.rotation_x += 0.1 + self.halley_comet.planet.rotation_y += 1 + # 摄像机始终看向二向箔 + camera_look_at(self.halley_comet) + + + +if __name__ == '__main__': + """ + 三体二向箔场景模拟 + """ + sim = HalleyCometSim() + sim.build() + # 订阅事件后,上面2个函数功能才会起作用 + # 运行中,每时每刻都会触发 on_timer_changed + UrsinaEvent.on_timer_changed_subscription(sim.on_timer_changed) + # 运行前会触发 on_ready + UrsinaEvent.on_ready_subscription(sim.on_ready) + # 使用 ursina 查看的运行效果 + # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 + # position = 左-右+、上+下-、前+后- + ursina_run(sim.bodies, + SECONDS_PER_WEEK, + # position=(0, 2 * AU, -11 * AU), + position=(0, 0.5 * AU, -5 * AU), + cosmic_bg='', + bg_music='sounds/no_glory.mp3', + show_camera_info=False, + show_control_info=False, + timer_enabled=True, + show_grid=False)