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

太阳系三体模拟器

上级 74d71709
......@@ -38,4 +38,4 @@ if __name__ == '__main__':
# mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45, view_distance=3e9, view_focalpoint=[5e2, 5e2, 5e2])
ursina_run(bodies, SECONDS_PER_YEAR, position=(0, 0, 0))
\ No newline at end of file
ursina_run(bodies, SECONDS_PER_WEEK, position=(0, 0, 0))
\ No newline at end of file
# -*- coding:utf-8 -*-
# title :ursina天体视图
# description :ursina天体视图(天体效果展示用,需要安装 ursina)
# author :Python超人
# date :2023-02-11
# link :https://gitcode.net/pythoncr/
# python_version :3.8
# ==============================================================================
# pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com ursina
from ursina import Ursina, window, Entity, Mesh, EditorCamera, color, mouse, Vec2, Vec3, load_texture,Texture
from math import pi, sin, cos
import numpy as np
import math
def create_sphere(radius, subdivisions):
"""
创建一个球体
:param radius:
:param subdivisions:
:return:
"""
# 生成球体的顶点、UV坐标uvs、法线tris和三角面
verts = []
tris = []
normals = []
uvs = []
for y in range(subdivisions + 1):
for x in range(subdivisions + 1):
x_segment = x / subdivisions
y_segment = -y / subdivisions
x_pos = cos(x_segment * 2 * pi) * sin(y_segment * pi)
y_pos = cos(y_segment * pi)
z_pos = sin(x_segment * 2 * pi) * sin(y_segment * pi)
verts.append(Vec3(x_pos, y_pos, z_pos) * radius)
uvs.append(Vec2(x_segment, y_segment))
normals.append(Vec3(x_pos, y_pos, z_pos))
for y in range(subdivisions):
for x in range(subdivisions):
first = (y * (subdivisions + 1)) + x
second = first + subdivisions + 1
# tris.append((first, second + 1, second))
# tris.append((first, first + 1, second + 1))
tris.append((second, second + 1, first))
tris.append((second + 1, first + 1, first))
# 反转面法线
# for i in range(len(tris)):
# a, b, c = tris[i]
# tris[i] = (c, b, a)
# normals[a], normals[b], normals[c] = -Vec3(*normals[c]), -Vec3(*normals[b]), -Vec3(*normals[a])
# normals[a], normals[b], normals[c] = -Vec3(*normals[a]), -Vec3(*normals[b]), -Vec3(*normals[c])
# 翻转球体
# for i in range(len(normals)):
# normals[i] = -normals[i]
return Mesh(vertices=verts, triangles=tris, normals=normals, uvs=uvs, mode='triangle')
def create_body_torus(inner_radius, outer_radius, subdivisions):
vertices = []
uvs = []
normals = []
triangles = []
# 计算圆环顶点、法向量和纹理坐标
for i in range(subdivisions):
for j in range(subdivisions):
# 计算纹理坐标
u = i / subdivisions
v = j / subdivisions
# 计算球面坐标系下的角度
theta = u * math.pi * 2
phi = v * math.pi * 2
# 计算圆环顶点位置
x = (outer_radius + inner_radius * math.cos(phi)) * math.cos(theta)
y = inner_radius * math.sin(phi) * (inner_radius / 20)
z = (outer_radius + inner_radius * math.cos(phi)) * math.sin(theta)
# 计算圆环顶点法向量
nx = math.cos(theta) * math.cos(phi)
ny = math.sin(phi)
nz = math.sin(theta) * math.cos(phi)
vertices.append((x, y, z))
normals.append((nx, ny, nz))
uvs.append((u, v))
# 计算圆环三角形面片
for i in range(subdivisions):
for j in range(subdivisions):
i1 = i
j1 = j
i2 = (i + 1) % subdivisions
j2 = (j + 1) % subdivisions
p1 = i1 * subdivisions + j1
p2 = i2 * subdivisions + j1
p3 = i2 * subdivisions + j2
p4 = i1 * subdivisions + j2
triangles.append((p1, p2, p3))
triangles.append((p1, p3, p4))
# uvs = [[u * 2, v] for u, v in uvs]
# 创建 mesh 对象
mesh = Mesh(vertices=vertices, uvs=uvs, normals=normals, triangles=triangles, mode='triangle')
return mesh
def create_torus(inner_radius, outer_radius, subdivisions):
verts = []
tris = []
for i in range(subdivisions):
angle = i * (360 / subdivisions)
x = np.cos(angle * np.pi / 180)
y = np.sin(angle * np.pi / 180)
# create vertices for inner radius
inner_x = x * inner_radius
inner_y = y * inner_radius
verts.append((inner_x, inner_y, 0))
# create vertices for outer radius
outer_x = x * outer_radius
outer_y = y * outer_radius
verts.append((outer_x, outer_y, 0))
# create triangles
first_index = i * 2
second_index = (i * 2 + 2) % (subdivisions * 2)
third_index = (i * 2 + 1) % (subdivisions * 2)
fourth_index = (i * 2 + 3) % (subdivisions * 2)
tris.append((first_index, second_index, third_index))
tris.append((third_index, second_index, fourth_index))
# create uvs
uvs = []
for i in range(len(verts)):
# 计算纹理坐标
u = i / subdivisions
v = i / subdivisions
angle = i * (360 / (subdivisions * 2))
u = -angle / 360
# v = angle / 360
# angle = i * (360 / (subdivisions * 2))
# u = angle / 360
# v = -(outer_radius - inner_radius) / outer_radius * 0.5
uvs.append((u, v))
# create normals
normals = []
for i in range(len(verts)):
angle = i * (360 / subdivisions)
x = np.cos(angle * np.pi / 180)
y = np.sin(angle * np.pi / 180)
normals.append((x, y, 0))
# create mesh
mesh = Mesh(vertices=verts, triangles=tris, uvs=uvs, normals=normals, mode='triangle')
# add color attribute
# mesh.colorize()
return mesh
if __name__ == '__main__':
app = Ursina()
# # 使用 Mesh 类创建球体
texture = "../../textures/saturn.jpg"
textureRings = '../../textures/saturnRings.jpg'
# 创建球体
sphere = create_sphere(1, 32)
entity = Entity(model=sphere, texture=texture, color=color.white)
# 创建光晕
# glow_entity = Entity(parent=entity, model='sphere', color=color.rgb(1,1,1,0.1),
# scale=2.1, alpha=0.1)
#
torus = create_body_torus(0.8, 2, 64)
textureRings = load_texture(textureRings)
# textureRings.wrap_x = 'repeat'
# textureRings.wrap_y = 'repeat'
# # 将纹理重复 2 次
# textureRings.uv_scale = (2, 2)
torus = create_torus(1.5, 3, 64)
entity = Entity(model=torus, texture=textureRings, rotation=(85, 0, 0), double_sided=True)
# entity.texture.repeat = 2
# entity.texture.apply()
# entity.texture.wrap_v = 'repeat'
# entity.texture.uv_scale = (2, 2)
# entity.texture.wrap = Texture.repeat
entity.texture.wrap_x = 2
entity.texture.wrap_y = 2
EditorCamera()
app.run()
......@@ -7,7 +7,8 @@
# python_version :3.8
# ==============================================================================
# pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com ursina
from ursina import Ursina, window, Entity, Mesh, SmoothFollow, Texture, clamp, time, camera, color, mouse, Vec2, Vec3, \
from ursina import Ursina, window, Entity, Mesh, SmoothFollow, Texture, clamp, time, \
camera, color, mouse, Vec2, Vec3, Vec4,\
load_texture, held_keys
# from ursina.camera import OrthographicCamera
......@@ -18,7 +19,9 @@ import random as rd
import os
from bodies import Body
import random
from simulators.views.body_view import BodyView
from simulators.views.ursina_mesh import create_sphere, create_body_torus
import numpy as np
import math
......@@ -32,6 +35,8 @@ class UrsinaPlayer(FirstPersonController):
"""
"""
body_rotation_speed_control = 1.0
def __init__(self, position, targets=None):
super().__init__()
......@@ -74,82 +79,6 @@ class UrsinaPlayer(FirstPersonController):
return super().input(key)
from math import pi, sin, cos
# def create_sphere(radius, subdivisions):
# # 生成球体的顶点、UV坐标、法线和三角面
# # radius = 1
# # subdivisions = 16
# theta = np.linspace(0, 2 * np.pi, subdivisions + 1)
# phi = np.linspace(0, np.pi, subdivisions + 1)
# u = np.linspace(0, 1, subdivisions + 1)
# v = np.linspace(0, 1, subdivisions + 1)
# verts = []
# uvs = []
# normals = []
# for i in range(len(theta)):
# for j in range(len(phi)):
# x = radius * np.sin(phi[j]) * np.cos(theta[i])
# y = radius * np.sin(phi[j]) * np.sin(theta[i])
# z = radius * np.cos(phi[j])
# verts.append((x, y, z))
# uvs.append((u[i], v[j]))
# normals.append((x / radius, y / radius, z / radius))
#
# tris = []
# for i in range(len(theta)):
# for j in range(len(phi)):
# a = i * (subdivisions + 1) + j
# b = (i + 1) * (subdivisions + 1) + j
# tris.append((a, b, a + 1))
# tris.append((a + 1, b, b + 1))
#
# # # 反转面法线
# # for i in range(len(tris)):
# # a, b, c = tris[i]
# # tris[i] = (c, b, a)
# # normals[a], normals[b], normals[c] = -Vec3(*normals[a]), -Vec3(*normals[b]), -Vec3(*normals[c])
# # normals[a], normals[b], normals[c] = -Vec3(*normals[a]), -Vec3(*normals[b]), -Vec3(*normals[c])
#
# # 创建球体 Mesh 对象并设置材质
# sphere_mesh = Mesh(vertices=verts, uvs=uvs, normals=normals, triangles=tris, mode='triangle')
# return sphere_mesh
def create_sphere(radius, subdivisions):
verts = []
tris = []
normals = []
uvs = []
for y in range(subdivisions + 1):
for x in range(subdivisions + 1):
x_segment = x / subdivisions
y_segment = y / subdivisions
x_pos = cos(x_segment * 2 * pi) * sin(y_segment * pi)
y_pos = cos(y_segment * pi)
z_pos = sin(x_segment * 2 * pi) * sin(y_segment * pi)
verts.append(Vec3(x_pos, y_pos, z_pos) * radius)
uvs.append(Vec2(x_segment, y_segment))
normals.append(Vec3(x_pos, y_pos, z_pos))
for y in range(subdivisions):
for x in range(subdivisions):
first = (y * (subdivisions + 1)) + x
second = first + subdivisions + 1
tris.append((first, second + 1, second))
tris.append((first, first + 1, second + 1))
# 反转面法线
for i in range(len(tris)):
a, b, c = tris[i]
tris[i] = (c, b, a)
# normals[a], normals[b], normals[c] = -Vec3(*normals[a]), -Vec3(*normals[b]), -Vec3(*normals[c])
return Mesh(vertices=verts, triangles=tris, normals=normals, uvs=uvs, mode='triangle')
class Planet(Entity):
def __init__(self, body_view: BodyView):
self.body_view = body_view
......@@ -160,7 +89,7 @@ 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
subdivisions = 32 # int(scale*20)
subdivisions = 32 # int(scale*20)
if hasattr(body_view, "texture"):
texture = load_texture(body_view.texture)
......@@ -174,7 +103,8 @@ class Planet(Entity):
texture=texture,
color=color.white,
position=pos,
rotation=(0, 0, 0))
rotation=(0, 0, 0),
double_sided=True)
def turn(self):
pos = self.body_view.position * SCALE_FACTOR
......@@ -215,17 +145,37 @@ class UrsinaView(BodyView):
if body.has_rings:
self.create_rings()
# self.create_glow()
#
# def create_glow(self):
# # self.body.color
# # for i in range(1):
# b_color = self.body.color
# color = Vec4(b_color[0], b_color[1], b_color[2], 0.2)
# # glow_entity = Entity(parent=self.planet, model='sphere', color=color,
# # scale=math.pow(1.2, i), alpha=0.2)
#
# glow_entity = Entity(parent=self.planet, model='sphere', color=color,
# scale=1.01, alpha=0.1)
# glow_entity.set_light_off()
def create_rings(self):
"""
创建行星环(使用土星贴图)
:return:
"""
# 行星环偏移角度
self.ring_rotation_x = 75
# 创建行星环
self.ring = Entity(parent=self.planet, model="circle", texture='../textures/saturnRings.jpg', scale=2,
# # # 行星环偏移角度
# self.ring_rotation_x = 80
# # 创建行星环
# self.ring = Entity(parent=self.planet, model='circle', texture='../textures/saturnRings.jpg', scale=3.5,
# rotation=(self.ring_rotation_x, 0, 0), double_sided=True)
self.ring_rotation_x = 0
torus = create_body_torus(0.3, 1, 32)
self.ring = Entity(parent=self.planet, model=torus, texture='../textures/saturnRings.jpg', scale=1,
rotation=(self.ring_rotation_x, 0, 0), double_sided=True)
# 设置行星环不受灯光影响,否则看不清行星环
self.ring.set_light_off()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册