From cb8a1e8dc66ec62ea47c197ec0ee4ad97af1067e Mon Sep 17 00:00:00 2001 From: march3 Date: Sun, 12 Nov 2023 17:00:59 +0800 Subject: [PATCH] =?UTF-8?q?Python=E8=B6=85=E4=BA=BA-=E5=AE=87=E5=AE=99?= =?UTF-8?q?=E6=A8=A1=E6=8B=9F=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sim_scenes/func.py | 54 +++++++++++- sim_scenes/solar_system/halley_comet_lib.py | 30 +++++++ sim_scenes/solar_system/halley_comet_sim.py | 95 +++++++++++++++------ tools/ffmpeg.md | 13 +++ 4 files changed, 160 insertions(+), 32 deletions(-) create mode 100644 tools/ffmpeg.md diff --git a/sim_scenes/func.py b/sim_scenes/func.py index f78e3ad..7bd33df 100644 --- a/sim_scenes/func.py +++ b/sim_scenes/func.py @@ -795,7 +795,7 @@ def get_run_speed_factor(run_speed_factor=1 / 8): return run_speed_factor * control_speed_factor -def camera_move_control(camera_move_infos, cond_cb, value_conv=None): +def camera_move_control(camera_move_infos, cond_cb, value_conv=None, smooth=None): """ @param camera_move_infos: @@ -809,6 +809,7 @@ def camera_move_control(camera_move_infos, cond_cb, value_conv=None): @param cond_cb: 条件回调,参数为: cond:当前条件数据, next_cond:下一个条件数据, idx:当前索引, info:当前信息, next_info:下一个信息 @param value_conv: + @param smooth: @return: """ from ursina import camera, Vec3 @@ -822,17 +823,57 @@ def camera_move_control(camera_move_infos, cond_cb, value_conv=None): return value_conv(val, p_name) return val + if smooth: + if not hasattr(camera, "last_move_ps"): + camera.last_move_ps = None + for idx, (cond, info) in enumerate(camera_move_infos[:-1]): next_cond = camera_move_infos[idx + 1][0] next_info = camera_move_infos[idx + 1][1] cond_cb_params = {"cond": cond, "next_cond": next_cond, "idx": idx, "info": info, "next_info": next_info} if cond_cb(cond_cb_params): p = camera.position - x, y, z = info.get("x", 0), info.get("y", 0), info.get("z", 0) - mis = info.get("f", 0), info.get("b", 0), info.get("l", 0), info.get("r", 0), \ - info.get("u", 0), info.get("d", 0) + x, y, z = [info.get("x", 0), info.get("y", 0), info.get("z", 0)] + mis = [info.get("f", 0), info.get("b", 0), info.get("l", 0), info.get("r", 0), \ + info.get("u", 0), info.get("d", 0)] dns = "fblrud" mas = camera.forward, camera.back, camera.left, camera.right, camera.up, camera.down + update_last_ps = False + if smooth: + if camera.last_move_ps is None: + update_last_ps = True + else: + ps = [x, y, z] + ps += mis + last_move_ps = camera.last_move_ps + diff = np.array(last_move_ps) - np.array(ps) + if not np.all(diff == 0): + update_last_ps = True + # print(diff) + if abs(diff[0]) < 0.05: + x = round(last_move_ps[0] - diff[0] / smooth, 2) + # print("x", x) + if abs(diff[1]) < 0.05: + y = round(last_move_ps[1] - diff[1] / smooth, 2) + # print("y", y) + if abs(diff[2]) < 0.05: + z = round(last_move_ps[2] - diff[2] / smooth, 2) + # print("z", z) + for _i in range(0, 6): + if abs(diff[_i + 3]) < 0.05: + mis[_i] = round(last_move_ps[_i + 3] - diff[_i + 3] / 100, 2) + # print(f"{dns[_i]}", mis[_i]) + # if diff[4] != 0: + # mis[1] = 0 + # if diff[5] != 0: + # z = 0 + # if diff[6] != 0: + # x = 0 + # if diff[7] != 0: + # y = 0 + # if diff[8] != 0: + # z = 0 + if x != 0 or y != 0 or z != 0: p += Vec3(conv_val(x, "x"), conv_val(y, "y"), conv_val(z, "z")) @@ -840,6 +881,11 @@ def camera_move_control(camera_move_infos, cond_cb, value_conv=None): if mi != 0: p += mas[i] * conv_val(mi, dns[i]) + if smooth and update_last_ps: + last_ps = [x, y, z] + last_ps += mis + camera.last_move_ps = last_ps + camera.position = p diff --git a/sim_scenes/solar_system/halley_comet_lib.py b/sim_scenes/solar_system/halley_comet_lib.py index 29b8d22..fe3e154 100644 --- a/sim_scenes/solar_system/halley_comet_lib.py +++ b/sim_scenes/solar_system/halley_comet_lib.py @@ -149,3 +149,33 @@ class HalleyCometSimBase(UniverseSimScenes): origin=origin, font="verdana.ttf", close_time=-1) + + def interval_run(self, total_times, interval, fun, fun_args=None): + """ + 需要注意的是 total_times 前后之间的间隔大于 interval,基本上是每次都运行。 + @param total_times: + @param interval: + @param fun: + @param fun_args: + @return: + """ + if not hasattr(self, "interval_method_register"): + self.interval_method_register = {} + + if fun not in self.interval_method_register.keys(): + self.interval_method_register[fun] = total_times + if fun_args is None: + fun() + elif len(fun_args) == 1: + fun(fun_args[0]) + elif len(fun_args) > 1: + fun(*fun_args) + else: + if total_times - self.interval_method_register[fun] > interval: + if fun_args is None: + fun() + elif len(fun_args) == 1: + fun(fun_args[0]) + elif len(fun_args) > 1: + fun(*fun_args) + self.interval_method_register[fun] = total_times diff --git a/sim_scenes/solar_system/halley_comet_sim.py b/sim_scenes/solar_system/halley_comet_sim.py index ad8711c..e3c5e31 100644 --- a/sim_scenes/solar_system/halley_comet_sim.py +++ b/sim_scenes/solar_system/halley_comet_sim.py @@ -13,6 +13,7 @@ from common.celestial_data_service import init_bodies_reality_pos_vels, conv_to_ set_solar_system_celestial_position from common.consts import SECONDS_PER_YEAR, AU from common.func import calculate_distance +from bodies import Earth from sim_scenes.func import create_text_panel, camera_look_at, get_run_speed_factor, \ camera_move_update, camera_move_to_target_update, camera_move_control from sim_scenes.func import ursina_run, create_sphere_sky @@ -54,6 +55,7 @@ class HalleyCometSim(HalleyCometSimBase): self.sun.glows = (80, 1.005, 0.01) # 创建哈雷彗星创建哈雷彗星 self.halley_comet = create_halley_comet(self.params.init_velocity, self.params.init_position) + self.bodies.append(self.halley_comet) def init_settings(self): @@ -88,7 +90,11 @@ class HalleyCometSim(HalleyCometSimBase): """ self.orbit_lines = [] for body in self.bodies[1:]: - orbit_line = create_orbit_line(self.sun, body, self.start_time) + if isinstance(body, Earth): + alpha = 0.5 + else: + alpha = 0.2 + orbit_line = create_orbit_line(self.sun, body, self.start_time, alpha=alpha) if orbit_line is not None: self.orbit_lines.append(orbit_line) @@ -115,8 +121,8 @@ class HalleyCometSim(HalleyCometSimBase): @return: """ # 为了不影响 2023年12月9日的显示,附近的 Label 就不显示 - if year in ["1986", "2061", "2023", "2024", "2025"]: - return + # if year in ["1986", "2061", "2023"]: + # return if trail is None: _pos = halley_comet_pos @@ -133,7 +139,9 @@ class HalleyCometSim(HalleyCometSimBase): scale=scale, alpha=1.0, background=background ) label.set_light_off() - self.last_year = year + # 只记录年 + if len(str(year)) == 4: + self.last_year = year def update_comet_trail_alpha(self, distance_sun): """ @@ -156,7 +164,7 @@ class HalleyCometSim(HalleyCometSimBase): else: alpha = MAX_ALPHA # 修改彗星尾巴的透明度 - c = self.halley_comet.planet.children[0] + c = self.halley_comet.planet.comet_trail c.alpha = alpha def show_milestone_lable(self, last_trail, dt): @@ -167,7 +175,7 @@ class HalleyCometSim(HalleyCometSimBase): @param dt: @return: """ - milestones = [("1986-02-09", (0, 2, 0)), ("2023-12-09", (0, 2, 0)), ("2061-07-28", (0, 2, 0))] + milestones = [("1986-02-09", (0, 2, 0)), ("2023-12-09", (0, 0, -3)), ("2061-07-28", (0, 3, 0))] for milestone, pos in milestones: prop_name = f"milestone_{milestone}" if not hasattr(self, prop_name) and dt.strftime("%Y-%m-%d") >= milestone: @@ -179,7 +187,7 @@ class HalleyCometSim(HalleyCometSimBase): background=True) # application.paused = True # UrsinaEvent.on_pause() - ControlUI.current_ui.on_off_switch.on_value_changed() + # ControlUI.current_ui.on_off_switch.on_value_changed() def s_f(self, value=1): if value == 0: @@ -198,19 +206,24 @@ class HalleyCometSim(HalleyCometSimBase): # 移动的信息: # 按坐标系方向移动 x:右+左-, y:升+降-, z:前+(接近太阳)后-(远离太阳) # 以摄像机视角移动 f:前 b:后 l:左 r:右 u:上 d:下 - (1982, {"x": 2, "y": 2, "z": 0}), - (1986, {"x": 2, "y": 2, "z": 2}), - (1996, {"x": 2, "y": 0, "z": 0, "f": 3}), - (2004, {"x": 0, "y": 0, "z": 0, "f": 3}), - (2006, {}), + (1982, {"x": 2, "y": 1}), + (1986, {"x": 2, "y": -2, "z": -15}), + (1987, {"y": -6, "z": -12}), + (1988, {"y": -3, "z": -12}), + (1989, {"z": -8, "f": -5}), + (1993, {"z": -8, "f": -3}), + (1995, {"z": -8}), + (2000, {"z": -8, "y": -0.2}), + (2013, {}), (2048, {"f": 3}), - (2061, {}), - (2124, {}), + (2062, {"y": -3}), + (2063, {"y": -4, "z": 2}), + (2072, {}), ] camera_move_control(camera_move_infos, cond_cb=lambda ps: ps["next_cond"] > dt.year >= ps["cond"], - value_conv=self.s_f) + value_conv=self.s_f, smooth=10) def check_create_year_label(self, last_trail, dt): """ @@ -328,12 +341,12 @@ class HalleyCometSim(HalleyCometSimBase): @param dt: @return: """ - if dt.year > 2045: - UrsinaConfig.trail_length = 211 + if dt.year > 2041: + UrsinaConfig.trail_length = 210 # 更新天体的位置 self.set_bodies_position(time_data) - # 更新时钟 - self.show_clock(dt) + # # 更新时钟 + # self.show_clock(dt) # 更新轨道的位置(TODO:短时间可以忽略) # for i, orbit_line in enumerate(self.orbit_lines): # orbit_line.position = self.sun.planet.position @@ -370,17 +383,43 @@ class HalleyCometSim(HalleyCometSimBase): time_total_hours = time_data.total_hours - if not hasattr(self, "last_total_hours"): - self.last_total_hours = time_total_hours - + # if not hasattr(self, "last_total_hours"): + # self.last_total_hours = time_total_hours + # self.update_halley_comet_info(dt) + # print("time_total_hours", time_total_hours) + # # 摄像机移动每10小时更新一次 + # self.interval_run(fun=self.camera_move, fun_args=[dt], + # total_times=time_total_hours, + # interval=20) self.camera_move(dt) - self.update_halley_comet_info(dt) - # 每隔一段时间运行一次更新(不要太频繁更新,会导致摄像机抖动) - if time_total_hours - self.last_total_hours > 100: - self.update_ui(time_data, dt) - # 记录最后更新的总耗时(小时) - self.last_total_hours = time_total_hours + if 2040 > dt.year > 1987: + update_halley_comet_info_interval = 400 + update_clock_interval = 400 + else: + update_halley_comet_info_interval = 33 + update_clock_interval = 60 + + # 更新哈雷彗星信息是每20个小时更新一次(哈雷彗星姿态、哈雷彗星距离信息) + self.interval_run(fun=self.update_halley_comet_info, fun_args=[dt], + total_times=time_total_hours, + interval=update_halley_comet_info_interval) + + # 每50个小时更新一次界面(天体位置) + self.interval_run(fun=self.update_ui, fun_args=[time_data, dt], + total_times=time_total_hours, + interval=60) + + self.interval_run(fun=self.show_clock, fun_args=[dt], + total_times=time_total_hours, + interval=update_clock_interval) + + # # 每隔一段时间运行一次更新(不要太频繁更新,会导致摄像机抖动) + # if time_total_hours - self.last_total_hours > 50: + # self.update_halley_comet_info(dt) + # self.update_ui(time_data, dt) + # # 记录最后更新的总耗时(小时) + # self.last_total_hours = time_total_hours if __name__ == '__main__': diff --git a/tools/ffmpeg.md b/tools/ffmpeg.md new file mode 100644 index 0000000..8fb4ef4 --- /dev/null +++ b/tools/ffmpeg.md @@ -0,0 +1,13 @@ +### ffmpeg 命令 + +```shell +# 视频截断 开始时间 -ss 结束时间 -to +# 修改视频的尺寸 -s +ffmpeg -i "input/一向箔.mp4" -s 450x255 -y -ss 00:00:09.0 -to 00:00:13.0 "output/一向箔.webp" +``` + +```shell +# -ss 00:00:02 表示从视频的第2秒开始截图 +# -vframes 1 表示只截取一帧 +ffmpeg -i "input/一向箔.mp4" -ss 00:00:02 -vframes 1 "output/一向箔.png" +``` \ No newline at end of file -- GitLab