提交 dbb7ae8f 编写于 作者: 三月三net's avatar 三月三net

太阳系三体模拟器

上级 56260282
......@@ -12,94 +12,12 @@ from ursina.prefabs.first_person_controller import FirstPersonController
from simulators.views.ursina_view import UrsinaView, UrsinaPlayer
# # -------------------------------------------------------------------------------
# app = Ursina()
# # window.fullscreen = True
# window.color = color.black
#
# planets = []
#
#
# class Planet(Entity):
# def __init__(self, _type, pos, texture, scale=2):
# self.angle = rd.uniform(0.0005, 0.01)
# self.fastMode = 0
# self.rotation = (rd.randint(0, 360) for i in range(3))
# self.rotspeed = rd.uniform(0.25, 1.5)
# self.rotMode = rd.choice(["x", "y", "z"])
# self._type = _type
# # texture = eval(f"{_type}_texture")
# texture = load_texture(texture)
# super().__init__(model="sphere",
# scale=scale,
# texture=texture,
# color=color.white,
# position=pos)
#
# def turn(self, angle):
# # if self._type != "sun":
# # if self.fastMode:
# # angle *= 200
# # self.x = self.x * cos(radians(angle)) - self.y * sin(radians(angle))
# # self.y = self.x * sin(radians(angle)) + self.y * cos(radians(angle))
# exec(f"self.rotation_{self.rotMode}+=self.rotspeed")
# #
# def input(self, key):
# if key == "enter":
# self.fastMode = 1 - self.fastMode
#
#
#
#
#
# def update():
# global planets, player
# for planet in planets:
# planet.turn(planet.angle)
# player._update()
#
# # os.chdir("../")
#
#
# # sun_texture = load_texture(texture_root + "sun.png")
# # mercury_texture = load_texture(texture_root + "mercury.png")
# # venus_texture = load_texture(texture_root + "venus.png")
# # earth_texture = load_texture(texture_root + "earth.png")
# # mars_texture = load_texture(texture_root + "mars.png")
# # jupiter_texture = load_texture(texture_root + "jupiter.png")
# # saturn_texture = load_texture(texture_root + "saturn.png")
# # uranus_texture = load_texture(texture_root + "uranus.png")
# # neptune_texture = load_texture(texture_root + "neptune.png")
#
# texture_root = "../textures/"
# ps = ["sun", "mercury", "venus", "earth", "mars", "jupiter", "saturn", "uranus", "neptune"]
# cp = [200, 15, 35, 42, 20, 160, 145, 90, 80] # 大小缩放
# x, y, z = 0, 0, 0
# for i, p in enumerate(ps):
# # _type, pos, texture, scale=2
# newPlanet = Planet(p, (x, y, z),texture_root+f"{p}.png", cp[i])
# planets.append(newPlanet)
# x += cp[i] * 10
#
# player = Player(planets)
#
# if __name__ == '__main__':
# # os.chdir("../")
# # sun_texture = os.path.join(texture_root, "sun.png")
# # print(os.path.exists(sun_texture))
# app.run()
#
# # ---------------------------------------------------------------------------
from simulators.simulator import Simulator
from common.system import System
import time
import datetime
from ursina import EditorCamera, PointLight, SpotLight, AmbientLight
player = None
class UrsinaSimulator(Simulator):
def __init__(self, bodies_sys: System):
......@@ -134,6 +52,11 @@ class UrsinaSimulator(Simulator):
super().evolve(self.evolve_dt)
def cosmic_background(self, texture='../textures/cosmic1.jpg'):
"""
加入宇宙背景
:param texture:
:return:
"""
# Add skybox
from ursina import Sky
Sky(texture=texture)
......@@ -207,7 +130,7 @@ if __name__ == '__main__':
Earth(init_position=[1.12 * AU, 0, 0],
init_velocity=[0, 29.79, 0], size_scale=4e3, distance_scale=1.3), # 地球放大 4000 倍,距离放大 1.3 倍
Moon(init_position=[363104 + 1.12 * AU, 0, 0],
init_velocity=[-9, 29.79 + 1.023, 0], size_scale=4e3, distance_scale=1.3),
init_velocity=[-9, 29.79 + 1.023, 0], size_scale=4e3, distance_scale=1.3),
Mars(size_scale=4e3, distance_scale=1.3), # 火星放大 4000 倍,距离放大 1.3 倍
Jupiter(size_scale=0.68e3, distance_scale=0.65), # 木星放大 680 倍,距离缩小到真实距离的 0.65
Saturn(size_scale=0.68e3, distance_scale=0.52), # 土星放大 680 倍,距离缩小到真实距离的 0.52
......
......@@ -21,72 +21,17 @@ import random
from simulators.views.body_view import BodyView
import numpy as np
import math
from math import sin, cos, radians
import os
import matplotlib.pyplot as plt
SCALE_FACTOR = 1e-6
class Ring(Entity):
def __init__(self, thickness=0.2, inner_radius=0.5, outer_radius=3, texture=None, position=None, **kwargs):
super().__init__(**kwargs)
inner_circle = Entity(parent=self, model='circle', texture=texture, scale=inner_radius,
position=position)
outer_circle = Entity(parent=self, model='circle', texture=texture, scale=outer_radius,
position=position)
self.children.append(inner_circle)
self.children.append(outer_circle)
inner_circle.parent = self
outer_circle.parent = self
inner_circle.set_light_off()
outer_circle.set_light_off()
# inner_circle.y += thickness / 2
# outer_circle.y -= thickness / 2
# self.scale_y = thickness
# 创建 TorusMesh
class TorusMesh(Mesh):
def __init__(self, radius=1, thickness=.25, radial_segments=16, tubular_segments=32):
super().__init__()
self.radius = radius
self.thickness = thickness
self.radial_segments = radial_segments
self.tubular_segments = tubular_segments
self.vertices = []
self.triangles = []
for j in range(radial_segments):
for i in range(tubular_segments):
a = i / tubular_segments * math.pi * 2
b = j / radial_segments * math.pi * 2
x = (radius + thickness * math.cos(b)) * math.cos(a)
y = (radius + thickness * math.cos(b)) * math.sin(a)
z = thickness * math.sin(b)
u = i / tubular_segments
v = j / radial_segments
self.vertices.append((x, y, z))
self.uvs.append((u, v))
for j in range(radial_segments):
for i in range(tubular_segments):
a = i
b = j
c = (i + 1) % tubular_segments
d = (j + 1) % radial_segments
self.triangles.append((a + b * tubular_segments, b + d * tubular_segments, c + b * tubular_segments))
self.triangles.append((c + b * tubular_segments, b + d * tubular_segments, c + d * tubular_segments))
class UrsinaPlayer(FirstPersonController):
"""
"""
class UrsinaPlayer(FirstPersonController):
def __init__(self, position, targets=None):
# global planets
super().__init__()
# pos = planets[0].position
camera.fov = 100
camera.rotation_y = 90
self.planets = None
......@@ -116,51 +61,6 @@ class UrsinaPlayer(FirstPersonController):
self.on_enable()
self.rotation_speed = 80
# def space_callback(self):
# best_camera_position = self.best_camera_position()
# if best_camera_position is None:
# return
# best_pos = np.array(best_camera_position[0]) * SCALE_FACTOR
# camera.position, camera.rotation = best_pos, best_camera_position[1]
#
# def best_camera_position(self):
# if self.planets is None:
# return None
#
# min_x, max_x, min_y, max_y, min_z, max_z = None, None, None, None, None, None
# for planet in self.planets:
# if min_x is None or planet.x < min_x:
# min_x = planet.x
# if max_x is None or planet.x > max_x:
# max_x = planet.x
# if min_y is None or planet.y < min_y:
# min_y = planet.y
# if max_y is None or planet.y > max_y:
# max_y = planet.y
# if min_z is None or planet.z < min_z:
# min_z = planet.z
# if max_z is None or planet.z > max_z:
# max_z = planet.z
# x = (min_x + max_x) / 2
# y = (min_y + max_y) / 2
# z = (min_z + max_z) / 2
# distance = max(max_x - min_x, max_y - min_y, max_z - min_z) * 1.5
# return (x, y + distance, z - distance), (0, -90, 0)
# def camera_adj(self, targets):
# # 创建一些物体
# # targets = []
# # for i in range(10):
# # targets.append(Entity(model='cube', color=color.random_color(), position=(i * 2 - 10, i % 2 * 2 - 1, 0)))
#
# # 计算所有物体的平均位置
# avg_pos = sum(np.array([target.position for target in targets]))/ len(targets)
#
# # 创建一个OrthographicCamera,使其位于所有目标的中心位置,并面向下方
# # camera = OrthographicCamera()
# camera.position = avg_pos + (0, 0, 20)
# camera.rotation_x = -90
def input(self, key):
if key == "escape":
if mouse.locked:
......@@ -168,55 +68,11 @@ class UrsinaPlayer(FirstPersonController):
else:
sys.exit()
return super().input(key)
# elif key == "space":
# self.space_callback()
# Input.bind('space', space_callback)
# def _update(self):
# # # {'left mouse': 0, 'left': 0, 'left shift': 0, 'space': 1, 'w': 0, 's': 0, 'd': 0, 'a': 0, 'shift': 0})
# # if held_keys["left mouse"]:
# # self.on_enable()
# # if held_keys["left shift"]:
# # self.y -= self.vspeed
# # if held_keys["space"]:
# # self.y += self.vspeed
# # WASD keys
#
# if held_keys['f']:
# camera.fov += 1
# if held_keys['r']:
# camera.fov -= 1
# # camera.position
# # self.rotation_y += held_keys['d'] * self.rotation_speed * time.dt
# # self.rotation_y -= held_keys['a'] * self.rotation_speed * time.dt
# # self.rotation_x += held_keys['w'] * self.rotation_speed * time.dt
# # self.rotation_x -= held_keys['s'] * self.rotation_speed * time.dt
#
# forward = self.forward * (held_keys['w'] - held_keys['s'])
# right = self.right * (held_keys['d'] - held_keys['a'])
#
# self.position += (forward + right) * self.speed * time.dt
# # if held_keys['w']:
# # camera.position += camera.forward * time.dt
# # if held_keys['s']:
# # camera.position -= camera.forward * time.dt
# # if held_keys['a']:
# # camera.position -= camera.right * time.dt
# # if held_keys['d']:
# # camera.position += camera.right * time.dt
# #
# # # Mouse control
# # camera.rotation_y += held_keys['right mouse'] * mouse.velocity[0] * 20
# # camera.rotation_x -= held_keys['right mouse'] * mouse.velocity[1] * 20
# # camera.rotation_x = clamp(camera.rotation_x, -90, 90)
class Planet(Entity):
def __init__(self, body_view: BodyView):
self.body_view = body_view
# self.angle = 0 # random.uniform(0.0005, 0.01)
# self.fastMode = 0
# self.rotation = (random.randint(0, 360) for i in range(3))
# 旋转速度和大小成反比(未使用真实数据)
self.rotspeed = 30000 / self.body_view.raduis # random.uniform(1.0, 2.0)
self.rotMode = 'x' # random.choice(["x", "y", "z"])
......@@ -225,18 +81,12 @@ class Planet(Entity):
pos = body_view.position * body_view.body.distance_scale * SCALE_FACTOR
scale = body_view.body.diameter * body_view.body.size_scale * SCALE_FACTOR
# texture = eval(f"{_type}_texture")
# e = os.path.exists(texture)
# texture = self.__set_texture(body_view.texture)
if hasattr(body_view, "texture"):
texture = load_texture(body_view.texture)
else:
texture = None
# 将贴图旋转90度C:\ProgramData\Anaconda3\envs\tf_gpu\Lib\site-packages\ursina\models_compressed\diamond.ursinamesh
super().__init__(
# model=TorusMesh(radius=1e20, thickness=1.25e20, radial_segments=16, tubular_segments=32),
# model="sky_dome",
model="sphere",
scale=scale,
texture=texture,
......@@ -244,30 +94,7 @@ class Planet(Entity):
position=pos,
rotation=(0, 0, 0))
# def __set_texture(self, image_file):
# """
# 设置纹理图片到天体
# :param image_file:
# :return:
# """
# outfile = image_file.replace('.png', '_rotate.png').replace('.jpg', '_rotate.jpg')
# from PIL import Image
# # 打开原始图片
# image = Image.open(image_file)
# # 顺时针旋转90度
# rotated_image = image.rotate(90, expand=True)
#
# # 保存旋转后的图片
# rotated_image.save(outfile)
#
# return outfile
def turn(self):
# if self.name != "sun":
# if self.fastMode:
# angle *= 200
# self.x = self.x * cos(radians(angle)) - self.y * sin(radians(angle))
# self.y = self.x * sin(radians(angle)) + self.y * cos(radians(angle))
pos = self.body_view.position * SCALE_FACTOR
self.x = -pos[1]
......@@ -289,35 +116,26 @@ class UrsinaView(BodyView):
def __init__(self, body: Body):
BodyView.__init__(self, body)
self.velocity = body.velocity
# 将列表元素往后移动一位,最后一位变为第一位
# a1 = a[1:] + [a[0]]
# self.velocity = np.concatenate((body.velocity[1:], [body.velocity[0]]))
# 将列表元素往前移动一位,第一位变为最后一位
# a2 = [a[-1]] + a[:-1]
# self.velocity = np.concatenate((np.array([body.velocity[-1]]), body.velocity[0:2]))
self.planet = Planet(self)
if body.has_rings:
self.create_rings()
# self.planet.clear_light()
if self.body.is_fixed_star:
# 如果是恒星(如:太阳),自身会发光,则需要关闭灯光
self.planet.set_light_off()
def create_rings(self):
from ursina import Cylinder
"""
创建星环(使用土星贴图)
:return:
"""
scale = 3 * self.body.diameter * self.body.size_scale * SCALE_FACTOR
pos = self.planet.position
# self.ring = Entity(model='sphere', texture='textures/saturnRings.jpg', scale=scale, position=pos,double_sided=True)
self.ring = Entity(model="circle", texture='../textures/saturnRings.jpg', scale=scale, position=pos,
rotation=(70, 0, 0), double_sided=True)
# self.ring2 = Entity(model="circle", texture='../textures/saturnRings.jpg', scale=scale, position=pos,
# rotation=(180 + 70, 0, 0))
# 假设星环自身会发光
self.ring.set_light_off()
# self.ring2.set_light_off()
def update(self):
self.planet.turn()
......@@ -325,8 +143,6 @@ class UrsinaView(BodyView):
self.light.position = Vec3(self.planet.x, self.planet.y, self.planet.z)
if hasattr(self, "ring"):
self.ring.position = Vec3(self.planet.x, self.planet.y, self.planet.z)
# if hasattr(self, "ring2"):
# self.ring2.position = Vec3(self.planet.x, self.planet.y, self.planet.z)
def appear(self):
pass
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册