From 4f522bade4c4a68a0a088b3d912d4b49cd72ba95 Mon Sep 17 00:00:00 2001 From: march3 Date: Thu, 30 Mar 2023 11:24:20 +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 --- bodies/__init__.py | 3 + bodies/body.py | 5 ++ bodies/color_body.py | 81 ++++++++++++++++++++++++ bodies/fixed_stars/fixed_star.py | 13 +++- common/image_utils.py | 17 ++++- sim_scenes/interest/text_bodies.py | 30 ++++----- sim_scenes/interest/the_eye_of_god.py | 25 +++----- sim_scenes/interest/utils/body_utils.py | 28 ++++++-- simulators/ursina/ui/control_handler.py | 25 +++++++- simulators/views/ursina_view.py | 13 ++-- textures/color_body.jpg | Bin 0 -> 27264 bytes 11 files changed, 188 insertions(+), 52 deletions(-) create mode 100644 bodies/color_body.py create mode 100644 textures/color_body.jpg diff --git a/bodies/__init__.py b/bodies/__init__.py index 19d9f39..fab8379 100644 --- a/bodies/__init__.py +++ b/bodies/__init__.py @@ -33,3 +33,6 @@ from bodies.fixed_stars.uy_scuti import UYScuti from bodies.fixed_stars.eta_carinae import EtaCarinae from bodies.fixed_stars.y_canum_venaticorum import YCanumVenaticorum from bodies.fixed_stars.carinae_v382 import CarinaeV382 + +# +from bodies.color_body import ColorBody diff --git a/bodies/body.py b/bodies/body.py index 08379d9..aa0a60c 100644 --- a/bodies/body.py +++ b/bodies/body.py @@ -86,6 +86,11 @@ class Body(metaclass=ABCMeta): self.show_name = show_name self.resolution = None + self.light_disable = False + + def set_light_disable(self, value): + self.light_disable = value + return self def set_resolution(self, value): self.resolution = value diff --git a/bodies/color_body.py b/bodies/color_body.py new file mode 100644 index 0000000..131ec70 --- /dev/null +++ b/bodies/color_body.py @@ -0,0 +1,81 @@ +# -*- coding:utf-8 -*- +# title :颜色天体 +# description :颜色天体 +# author :Python超人 +# date :2023-02-11 +# link :https://gitcode.net/pythoncr/ +# python_version :3.8 +# ============================================================================== +from bodies.body import Body +from common.consts import MO +from common.image_utils import gen_color_body_texture, find_texture_root_path +import os +import random + + +class ColorBody(Body): + """ + 颜色天体基类 + """ + + def __init__(self, name="颜色天体", mass=1 * MO, + init_position=[0, 0, 0], + init_velocity=[0, 0, 0], + color=(0xFF, 0xFF, 0xFF), + texture=None, size_scale=1.0, distance_scale=1.0, + rotation_speed=None, ignore_mass=False, density=5e3, trail_color=None, + texture_bright=None, texture_contrast=None, show_name=False): + + self.color = color + texture = self.gen_texture(texture, texture_bright, texture_contrast) + if rotation_speed is None: + rotation_speed = random.randint(10, 100) / 50 + 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, + "rotation_speed": rotation_speed, + "ignore_mass": ignore_mass, + "trail_color": trail_color, + "show_name": show_name + } + super().__init__(**params) + + def gen_texture(self, texture, texture_bright, texture_contrast): + if texture is None: + return None + texture_path = find_texture_root_path() + if texture_path is None: + err_msg = "未找到纹理图片目录" + raise Exception(err_msg) + + temp_dir = os.path.join(texture_path, "temp") + if not os.path.exists(temp_dir): + os.mkdir(temp_dir) + + texture_name = os.path.basename(texture). \ + replace(".", "_").replace("/", "_"). \ + replace("\\", "_").replace("__", "_") + + save_file = os.path.join(temp_dir, "%s_%s.png" % (texture_name, "_".join([str(i) for i in list(self.color)]))) + + if os.path.exists(save_file): + return save_file + + body_img = os.path.join(texture_path, texture) + gen_color_body_texture(self.color, + bright=texture_bright, + contrast=texture_contrast, + save_file=save_file, + color_body_img=body_img) + return save_file + + +if __name__ == '__main__': + print(ColorBody()) diff --git a/bodies/fixed_stars/fixed_star.py b/bodies/fixed_stars/fixed_star.py index 70ec1dd..c60ed07 100644 --- a/bodies/fixed_stars/fixed_star.py +++ b/bodies/fixed_stars/fixed_star.py @@ -1,6 +1,6 @@ # -*- coding:utf-8 -*- -# title :天狼星 -# description :天狼星 +# title :恒星 +# description :恒星 # author :Python超人 # date :2023-02-11 # link :https://gitcode.net/pythoncr/ @@ -49,6 +49,7 @@ class FixedStar(Body): "show_name": show_name } super().__init__(**params) + # 恒星属性 self.light_on = True self.glows = (12, 1.009, 0.08) @@ -59,9 +60,15 @@ class FixedStar(Body): if texture_path is None: err_msg = "未找到纹理图片目录" raise Exception(err_msg) - save_file = os.path.join(texture_path, "fixed_star_%s.png" % str(self.__class__.__name__).lower()) + + temp_dir = os.path.join(texture_path, "temp") + if not os.path.exists(temp_dir): + os.mkdir(temp_dir) + + save_file = os.path.join(temp_dir, "fixed_star_%s.png" % str(self.__class__.__name__).lower()) if os.path.exists(save_file): return save_file + fixed_star_img = os.path.join(texture_path, texture) gen_fixed_star_texture(self.color, bright=texture_bright, diff --git a/common/image_utils.py b/common/image_utils.py index 1e40748..bf870c8 100644 --- a/common/image_utils.py +++ b/common/image_utils.py @@ -194,6 +194,21 @@ def find_texture(texture): return "" +def gen_color_body_texture(color, save_file, color_body_img="color_body.jpg", bright=None, contrast=None): + bright = 1 if bright is None else bright + contrast = 1 if contrast is None else contrast + color_body_img = find_texture(color_body_img) + if color_body_img is None: + err_msg = "未找到纹理图片:" % color_body_img + raise Exception(err_msg) + trans_img = trans_png(color_body_img) + bg_img = create_image(trans_img.width, trans_img.height, color) + mixed = mix(bg_img, trans_img) + mixed = image_enhance(mixed, bright=bright, contrast=contrast) + mixed.save(save_file, 'PNG') + return mixed + + def gen_fixed_star_texture(color, save_file, fixed_star_img="fixed_star.png", bright=None, contrast=None): bright = 1.1 if bright is None else bright contrast = 3.2 if contrast is None else contrast @@ -250,7 +265,7 @@ if __name__ == '__main__': # mono = gray_to_mono(gray_img, (0, 0, 255)).show() # image_enhance(mono,bright=1,contrast=2).show() - gen_fixed_star_texture((198, 29, 3), "xxx.png",bright=2.2,contrast=3).show() + gen_fixed_star_texture((198, 29, 3), "xxx.png", bright=2.2, contrast=3).show() # fixed_star_img = find_texture("sun.png") # colorize_color(fixed_star_img,(0,0xff,0xff)).show() diff --git a/sim_scenes/interest/text_bodies.py b/sim_scenes/interest/text_bodies.py index 7769a02..a4b350b 100644 --- a/sim_scenes/interest/text_bodies.py +++ b/sim_scenes/interest/text_bodies.py @@ -6,7 +6,7 @@ # link :https://gitcode.net/pythoncr/ # python_version :3.8 # ============================================================================== -from bodies import Sun, Earth, Moon, FixedStar, Body +from bodies import Sun, Earth, Moon, FixedStar, ColorBody from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY, SECONDS_PER_WEEK from sim_scenes.func import mayavi_run, ursina_run from bodies.body import AU @@ -18,30 +18,22 @@ def show_text_bodies(): """ 显示文本的星球群 """ - D = 600 - mass = 0.5e25 + D = 6000 # camera_pos = 左-右+、上+下-、前+后- - camera_pos = (-100 * D, 0, -5000 * D) + camera_pos = (-130 * D, 0, -6000 * D) - def get_position(pos, scale): - # [ 远+近- , 左+右- , 上+下-] - return pos[0] + (scale - 1.0) * 200 * (random.randint(90, 110)) * D, pos[1], pos[2] - # return pos[0], pos[1], pos[2] - - bodies: list = gen_bodies_from_image(pixel_image="./images/python.png", - params={"D": D, "Body": Body, "mass": mass, - "get_position": get_position, - "camera_pos": camera_pos}) - face = FixedStar(name="bg", texture="fixed_star.png", mass=mass * 9000, color=(0xff, 0xf8, 0xd4), - init_position=[2000 * D, 260 * D, 100 * D], # [ 远+近- , 左+右- , 上+下-] - ignore_mass=True) - face.light_on = False - bodies.append(face) + bodies: list = gen_bodies_from_image(pixel_image="./images/python.png", texture="color_body.jpg", + params={"camera_pos": camera_pos}) + bg = FixedStar(name="bg", texture="fixed_star.png", mass=5e31, color=(0xff, 0xf8, 0xd4), + init_position=[3000 * D, 260 * D, 100 * D], # [ 远+近- , 左+右- , 上+下-] + ignore_mass=True) + bg.light_on = True + bodies.append(bg) # 使用 ursina 查看的运行效果 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # position = 左-右+、上+下-、前+后- - ursina_run(bodies, SECONDS_PER_WEEK * 2, position=camera_pos) + ursina_run(bodies, SECONDS_PER_WEEK * 2, position=camera_pos, view_closely=True) if __name__ == '__main__': diff --git a/sim_scenes/interest/the_eye_of_god.py b/sim_scenes/interest/the_eye_of_god.py index ed0cd86..a6feaa6 100644 --- a/sim_scenes/interest/the_eye_of_god.py +++ b/sim_scenes/interest/the_eye_of_god.py @@ -17,29 +17,22 @@ def show_eye_of_god(): """ 上帝之眼 """ - D = 600 - mass = 0.9e25 + D = 6000 # camera_pos = 左-右+、上+下-、前+后- - camera_pos = (-100 * D, 0, -5000 * D) - - def get_position(pos, scale): - # [ 远+近- , 左+右- , 上+下-] - return pos[0] + (scale - 1.0) * 300 * (random.randint(90, 110)) * D, pos[1], pos[2] - # return pos[0], pos[1], pos[2] + camera_pos = (-100 * D, 0, -6000 * D) bodies: list = gen_bodies_from_image(pixel_image="./images/eye.png", - params={"D": D, "Body": Body, "mass": mass, - "get_position": get_position, "camera_pos": camera_pos}) - face = FixedStar(name="face", texture="fixed_star.png", mass=mass * 3000, color=(0xff, 0xf8, 0xd4), - init_position=[2000 * D, 200 * D, 100 * D], # [ 远+近- , 左+右- , 上+下-] - ignore_mass=True) - face.light_on = False - bodies.append(face) + params={"camera_pos": camera_pos}) + bg = FixedStar(name="bg", texture="fixed_star.png", mass=5e31, color=(0xff, 0xf8, 0xd4), + init_position=[3000 * D, 200 * D, 100 * D], # [ 远+近- , 左+右- , 上+下-] + ignore_mass=True) + # bg.light_on = False + bodies.append(bg) # 使用 ursina 查看的运行效果 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # position = 左-右+、上+下-、前+后- - ursina_run(bodies, SECONDS_PER_WEEK * 2, position=camera_pos) + ursina_run(bodies, SECONDS_PER_WEEK * 2, position=camera_pos, view_closely=True) if __name__ == '__main__': diff --git a/sim_scenes/interest/utils/body_utils.py b/sim_scenes/interest/utils/body_utils.py index 1a7533a..a841749 100644 --- a/sim_scenes/interest/utils/body_utils.py +++ b/sim_scenes/interest/utils/body_utils.py @@ -6,24 +6,38 @@ # link :https://gitcode.net/pythoncr/ # python_version :3.8 # ============================================================================== +from bodies import ColorBody +import random +from PIL import Image -def gen_bodies_from_image(pixel_image, params, body_template=None): + +def gen_bodies_from_image(pixel_image, params, texture="color_body.png"): """ 根据像素图片以及参数,自动生成星球,注意图片像素不能太多,否则会导致电脑运行太慢 @param pixel_image: @param params: @return: """ - from PIL import Image + D = 6000 + mass = 0.9e25 + + def get_position(pos, scale): + # [ 远+近- , 左+右- , 上+下-] + return pos[0] + (scale - 1.0) * 300 * (random.randint(90, 110)) * D, pos[1], pos[2] + # return pos[0], pos[1], pos[2] + + params["ColorBody"] = ColorBody + params["get_position"] = get_position + params["mass"] = mass + params["D"] = D img = Image.open(pixel_image).convert('RGBA') width, height = img.size interval_factor = 20 # 星球间距因子 - if body_template is None: - body_template = 'Body(name="%s", mass=mass, color=(%d, %d, %d), size_scale=%.4f, ' \ - 'init_position=get_position([0, %g * D, %g * D], %.4f), ' \ - 'init_velocity=[0, 0, 0], ignore_mass=True)' + body_template = 'ColorBody(name="%s", mass=mass, color=(%d, %d, %d), size_scale=%.4f, ' \ + 'init_position=get_position([0, %g * D, %g * D], %.4f), ' \ + f'init_velocity=[0, 0, 0], ignore_mass=True, texture="{texture}").set_light_disable(True)' bodies_str = "[" # 以图片像素为坐标,对角线的距离 @@ -44,7 +58,7 @@ def gen_bodies_from_image(pixel_image, params, body_template=None): # 对于纯白色的颜色,就忽略,不生成星球(这样图片中,纯白色越多,对电脑的压力就越小) if pixel[0] >= 255 and pixel[1] >= 255 and pixel[1] >= 255: continue - body_str = body_template % (f"星球{w}:{h}", pixel[0], pixel[1], pixel[2], scale, + body_str = body_template % (f"星球{w}:{h}", pixel[0], pixel[1], pixel[2], scale * 10, (width - w) * interval_factor, (height - h) * interval_factor, scale) bodies_str += body_str + ",\n" diff --git a/simulators/ursina/ui/control_handler.py b/simulators/ursina/ui/control_handler.py index d508ae1..d54683f 100644 --- a/simulators/ursina/ui/control_handler.py +++ b/simulators/ursina/ui/control_handler.py @@ -36,6 +36,26 @@ class ControlHandler(EventHandler): key_info = Text(text=key_info_str, font=UrsinaConfig.CN_FONT, position=(-1, 0.5), origin=(-1, 1), background=True) + self.camera_info = Text(text="", scale=0.8, position=(0, -0.45), origin=(0, 1), + background=True) + + def camera_update(self): + pos = camera.position # WS => [2] + w_pos = camera.world_rotation # 鼠标右键 + # rot = camera.rotation + wt = camera.world_transform # QE[0,1,2] AD [0 , 2] 鼠标右键 + # print(camera.world_transform) + # print(camera.origin, camera.world_transform) + # LVector3f(-1, 0, 0) Vec3(0, 0, 1) LVector3f(0, 0, -1) Vec3(1, 0, 0) Vec3(1, 1, 1) 1.7777777910232544 LVector3f(0, -1, 0) Vec3(0, 1, 0) Vec3(1, 1, 1) Vec3(0, 0, 0) + # print(camera.left,camera.forward,camera.back,camera.right,camera.scale,camera.aspect_ratio,camera.down,camera.up,camera.world_scale,camera.world_rotation) + # fw = camera.forward + # self.camera_info.text = "pos:[%.2f,%.2f,%.2f] w_pos:[%.2f,%.2f,%.2f] rot:[%.2f,%.2f,%.2f] wt:[%s,%s,%s]" % \ + self.camera_info.text = "pos:[%.2f,%.2f,%.2f] w_pos:[%.2f,%.2f,%.2f] wt:[%s,%s]" % \ + (pos[0], pos[1], pos[2], + w_pos[0], w_pos[1], w_pos[2], + # rot[0], rot[1], rot[2], + wt[0], wt[1]) # , wt[2] + def sec_per_time_switch_changed(self): """ 按钮组("默认", "天", "周", "月", "年", "十年", "百年") 点击 @@ -195,6 +215,9 @@ class ControlHandler(EventHandler): @return: """ import sys + + self.camera_update() + if key == "escape": sys.exit() # print(key) @@ -230,7 +253,7 @@ class ControlHandler(EventHandler): import math # min=0.01, max=20 # # ', up' < > '. up' n m - self.ui.slider_control_speed_factor.current_step = self.ui.slider_control_speed_factor.value/2 + self.ui.slider_control_speed_factor.current_step = self.ui.slider_control_speed_factor.value / 2 self.slider_decrease(self.ui.slider_control_speed_factor, self.ui.slider_control_speed_factor.current_step) print(self.ui.slider_control_speed_factor.current_step) diff --git a/simulators/views/ursina_view.py b/simulators/views/ursina_view.py index 71d41d9..3e1560b 100644 --- a/simulators/views/ursina_view.py +++ b/simulators/views/ursina_view.py @@ -130,18 +130,21 @@ class Planet(Entity): double_sided=True ) - if hasattr(self.body_view.body, "torus_stars") or \ - hasattr(self.body_view.body, "light_disable"): + if hasattr(self.body_view.body, "torus_stars"): # 星环小天体群(主要模拟小行星群,非一个天体) - # 或者灯光禁用 self.set_light_off() self.double_sided = True else: # 一个天体 # 拖尾球体的初始化 self.trail_init() - if self.body_view.body.is_fixed_star: - self.create_fixed_star_lights() + + if self.body_view.body.is_fixed_star: + # 如果是恒星,开启恒星的发光的效果、并作为灯光源 + self.create_fixed_star_lights() + elif self.body_view.body.light_disable: + # 如果是非恒星,并且禁用灯光 + self.set_light_off() if self.body_view.body.show_name: self.create_name_text() diff --git a/textures/color_body.jpg b/textures/color_body.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0dcedd3748d6cd93759932295fd31e3c25b4d60d GIT binary patch literal 27264 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