diff --git a/objs/halley_comet.py b/objs/halley_comet.py index 3fda72e391922caab5cd06857e4500a35706ab9b..c19b3e8384d40eaa16fdba3a089502661eebb72a 100644 --- a/objs/halley_comet.py +++ b/objs/halley_comet.py @@ -25,7 +25,7 @@ class HalleComet(RockSnow): init_position=[0, 0, 0], init_velocity=[0, 0, 0], size_scale=1.0, distance_scale=1.0, - ignore_mass=False, density=1e3, color=(7, 0, 162), + ignore_mass=False, density=1e3, color=(255, 255, 255), trail_color=None, show_name=False, rotation=(0, 0, 0), parent=None, gravity_only_for=[]): @@ -37,6 +37,7 @@ class HalleComet(RockSnow): "density": density, "color": color, "size_scale": size_scale, + "texture": "comet.jpg", "distance_scale": distance_scale, "ignore_mass": ignore_mass, "trail_color": trail_color, @@ -46,6 +47,8 @@ class HalleComet(RockSnow): "gravity_only_for": gravity_only_for, } super().__init__(**params) + # create_cone(radius, height, subdivisions, r=0.1) + self.comet_info = (0.18, 1.5, 100, 0.2) from ursina.prefabs.primitives import Shader diff --git a/objs/textures/comet.jpg b/objs/textures/comet.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1b7d0a15891cb598130d2944288c9d614c232195 Binary files /dev/null and b/objs/textures/comet.jpg differ diff --git a/objs/textures/comet_trail.png b/objs/textures/comet_trail.png new file mode 100644 index 0000000000000000000000000000000000000000..b4f5d46dff833a367f172bec9cf77fe6327f966f Binary files /dev/null and b/objs/textures/comet_trail.png differ diff --git a/sim_scenes/solar_system/halley_comet_sim.py b/sim_scenes/solar_system/halley_comet_sim.py index c0cba01e1458a82eea7be01bd5f0bf2778619308..bc520efd2daa1f0cfb7ec08f809a3a8078332b6e 100644 --- a/sim_scenes/solar_system/halley_comet_sim.py +++ b/sim_scenes/solar_system/halley_comet_sim.py @@ -116,8 +116,9 @@ class HalleyCometSim: """ # 哈雷彗星飞行的翻转效果 if self.halley_comet.planet.enabled: - self.halley_comet.planet.rotation_x += 0.1 - self.halley_comet.planet.rotation_y += 1 + # self.halley_comet.planet.rotation_x += 0.1 + # self.halley_comet.planet.rotation_y += 1 + self.halley_comet.planet.look_at(self.sun.planet) # 摄像机始终看向哈雷彗星 # camera_look_at(self.halley_comet) d = calculate_distance(self.halley_comet.position, self.sun.position) diff --git a/sim_scenes/solar_system/halley_comet_sim_02.py b/sim_scenes/solar_system/halley_comet_sim_02.py index 0dfa7b478be39948be8733afbdf1b44d28cec40c..315d77ce0ad4572a96b8d4b916a413d050a586f0 100644 --- a/sim_scenes/solar_system/halley_comet_sim_02.py +++ b/sim_scenes/solar_system/halley_comet_sim_02.py @@ -145,8 +145,10 @@ class HalleyCometSim: if hasattr(self, "halley_comet"): # 哈雷彗星飞行的翻转效果 if self.halley_comet.planet.enabled: - self.halley_comet.planet.rotation_x += 0.1 - self.halley_comet.planet.rotation_y += 1 + # self.halley_comet.planet.rotation_x += 0.1 + # self.halley_comet.planet.rotation_y += 1 + self.halley_comet.planet.look_at(self.sun.planet) + d = calculate_distance(self.halley_comet.position, self.sun.position) self.text_panel.text = "哈雷彗星距离太阳:%.3f AU" % (d / AU) diff --git a/sim_scenes/solar_system/halley_comet_sim_03.py b/sim_scenes/solar_system/halley_comet_sim_03.py index e3817869c994612c28010da99681d6035935acd1..56e07c92a699679a2cde8d1cc7d2e0b5a281f37a 100644 --- a/sim_scenes/solar_system/halley_comet_sim_03.py +++ b/sim_scenes/solar_system/halley_comet_sim_03.py @@ -191,8 +191,10 @@ class HalleyCometSim: if hasattr(self, "halley_comet"): # 哈雷彗星飞行的翻转效果 if self.halley_comet.planet.enabled: - self.halley_comet.planet.rotation_x += 0.1 - self.halley_comet.planet.rotation_y += 1 + # self.halley_comet.planet.rotation_x += 0.1 + # self.halley_comet.planet.rotation_y += 1 + self.halley_comet.planet.look_at(self.sun.planet) + d_sun = calculate_distance(self.halley_comet.position, self.sun.position) d_earth = calculate_distance(self.halley_comet.position, self.earth.position) trail_keys = self.halley_comet.planet.trails.keys() diff --git a/simulators/ursina/entities/planet.py b/simulators/ursina/entities/planet.py index 8bdd8d05827ef0ba90cbdd5d455d4c7e2de7e310..adeaf26dfe5669fbabaeecdb439f9bc9d188f184 100644 --- a/simulators/ursina/entities/planet.py +++ b/simulators/ursina/entities/planet.py @@ -9,6 +9,7 @@ # pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com ursina from ursina import application, Entity, camera, color, Vec3, Text, load_texture, destroy, PointLight +from common.image_utils import find_texture from simulators.ursina.entities.entity_utils import create_name_text, create_trails, clear_trails, create_rings, \ trail_init, create_fixed_star_lights from simulators.ursina.ursina_config import UrsinaConfig @@ -16,7 +17,8 @@ from simulators.ursina.ursina_event import UrsinaEvent from common.color_utils import adjust_brightness, conv_to_vec4_color, get_inverse_color from common.func import find_file from simulators.views.body_view import BodyView -from simulators.ursina.ursina_mesh import create_sphere, create_torus, create_arrow_line, create_line, create_label +from simulators.ursina.ursina_mesh import create_sphere, create_torus, create_arrow_line, create_line, create_label, \ + create_cone import math @@ -168,6 +170,9 @@ class Planet(Entity): # 如果是非恒星,并且禁用灯光 self.set_light_off() + if hasattr(self.body, "comet_info"): + self.create_comet_trail(self.body.comet_info) + if self.body.show_name: create_name_text(self) @@ -176,6 +181,17 @@ class Planet(Entity): # 创建行星环(目前只有土星环) create_rings(self) + def create_comet_trail(self, comet_info): + # cone = create_cone(0.25, 1.5, 100, 0.18) + cone = create_cone(*comet_info) + texture = find_texture("comet_trail.png") + self.comet_trail = Entity(parent=self, model=cone, texture=texture, scale=20, + position=(0, 0, 0), + rotation=(0, 90, 90), double_sided=True, alpha=0.8) + + # 设置行星环不受灯光影响,否则看不清行星环 + self.comet_trail.set_light_off() + def create_rotate_entity(self): """ diff --git a/simulators/ursina/ursina_mesh.py b/simulators/ursina/ursina_mesh.py index d5bb0fc5a72959e7547fee26c50289a4893ab55a..1ba393811f6813e61b61fae7451aeb659464710d 100644 --- a/simulators/ursina/ursina_mesh.py +++ b/simulators/ursina/ursina_mesh.py @@ -69,6 +69,97 @@ def create_sphere(radius, subdivisions): return Mesh(vertices=verts, triangles=tris, normals=normals, uvs=uvs, mode='triangle') +def create_cone(radius, height, subdivisions, r=0.1): + """ + 创建一个圆锥 + @param radius: 圆锥底部的半径 + @param height: 圆锥的高度 + @param subdivisions: 细分数,用于控制圆锥的光滑度 + @return: Mesh对象,表示创建的圆锥 + """ + verts = [] # 顶点列表 + tris = [] # 三角面索引列表 + normals = [] # 法线列表 + uvs = [] # UV坐标列表 + + p_h = r*height + d_h = (1-r)*height + + # 生成圆锥底部的顶点和UV坐标 + for i in range(subdivisions): + angle = 2 * math.pi * i / subdivisions + x = radius * math.cos(angle) + z = radius * math.sin(angle) + verts.append(Vec3(x, d_h, z)) + uvs.append(Vec2(i / subdivisions, 0)) + + # 圆锥尖端的顶点 + verts.append(Vec3(0, -p_h, 0)) + uvs.append(Vec2(0.5, 1)) + + # 生成圆锥侧面的顶点、法线和三角面 + for i in range(subdivisions): + p1 = verts[i] + p2 = verts[(i + 1) % subdivisions] + # 侧面三角形 + tris.append((i, (i + 1) % subdivisions, subdivisions)) + # 侧面法线 + normal = Vec3(0, 1, 0).cross(p2 - p1).normalized() + normals.append(normal) + + return Mesh(vertices=verts, triangles=tris, normals=normals, uvs=uvs, mode='triangle') + + +def create_cylinder(radius, height, subdivisions): + """ + 创建一个圆柱体 + @param radius: 圆柱体的底部半径 + @param height:圆柱体的高度 + @param subdivisions: 细分数,用于控制圆柱体的光滑度 + @return: Mesh对象,表示创建的圆柱体 + """ + # 生成圆锥的顶点、UV坐标uvs、法线normals和三角面tris + verts = [] + tris = [] + normals = [] + uvs = [] + + # 生成底面顶点和法线 + verts.append(Vec3(0, 0, 0)) + normals.append(Vec3(0, -1, 0)) + for x in range(subdivisions + 1): + angle = x / subdivisions * 2 * pi + x_pos = cos(angle) * radius + z_pos = sin(angle) * radius + verts.append(Vec3(x_pos, 0, z_pos)) + normals.append(Vec3(0, -1, 0)) + + # 生成侧面顶点、法线和纹理坐标 + for y in range(subdivisions + 1): + for x in range(subdivisions + 1): + angle = x / subdivisions * 2 * pi + x_pos = cos(angle) * radius * (1 - y / subdivisions) + y_pos = -height + (y / subdivisions) * height + z_pos = sin(angle) * radius * (1 - y / subdivisions) + verts.append(Vec3(x_pos, y_pos, z_pos)) + normals.append(Vec3(cos(angle), radius / height, sin(angle))) + uvs.append(Vec2(x / subdivisions, y / subdivisions)) + + # 生成底面三角面 + for x in range(subdivisions): + tris.append((0, x + 2, x + 1)) + + # 生成侧面三角面 + for y in range(subdivisions): + for x in range(subdivisions): + first = (y * (subdivisions + 1)) + x + 1 + second = first + subdivisions + 1 + tris.append((first, second, first + 1)) + tris.append((second, second + 1, first + 1)) + + return Mesh(vertices=verts, triangles=tris, normals=normals, uvs=uvs, mode='triangle') + + def create_arrow(height=0.5, width=0.1): # 创建金字塔的顶点 r = width / 2