ursina_view.py 4.8 KB
Newer Older
三月三net's avatar
三月三net 已提交
1 2 3 4 5 6 7 8 9
# -*- 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
M
march3 已提交
10 11 12 13
from ursina import Ursina, window, Entity, Mesh, SmoothFollow, Texture, clamp, time, camera, color, mouse, Vec2, Vec3, \
    load_texture, held_keys

# from ursina.camera import OrthographicCamera
M
march3 已提交
14 15 16 17 18
from math import sin, cos, radians
from ursina.prefabs.first_person_controller import FirstPersonController
import sys
import random as rd
import os
三月三net's avatar
三月三net 已提交
19 20 21 22
from bodies import Body
import random
from simulators.views.body_view import BodyView
import numpy as np
M
march3 已提交
23
import math
三月三net's avatar
三月三net 已提交
24

三月三net's avatar
三月三net 已提交
25
SCALE_FACTOR = 1e-6
M
march3 已提交
26 27


三月三net's avatar
三月三net 已提交
28 29
class UrsinaPlayer(FirstPersonController):
    """
M
march3 已提交
30

三月三net's avatar
三月三net 已提交
31
    """
M
march3 已提交
32

M
march3 已提交
33
    def __init__(self, position, targets=None):
M
march3 已提交
34 35
        super().__init__()
        camera.fov = 100
M
march3 已提交
36 37
        camera.rotation_y = 90
        self.planets = None
M
march3 已提交
38
        if targets is not None:
M
march3 已提交
39
            self.planets = []
M
march3 已提交
40
            # targets = [view.planet.parent for view in targets]
M
march3 已提交
41
            # targets_parent = Entity()
M
march3 已提交
42
            for view in targets:
M
march3 已提交
43 44 45 46 47 48
                # view.planet.parent = targets_parent
                self.planets.append(view.planet)
            # self.camera_adj(planets)
            #     # planets.append(view.planet)
            #
            # camera.add_script(SmoothFollow(targets_parent, offset=(0, 8, -20)))
M
march3 已提交
49 50
        pos = np.array(position) * SCALE_FACTOR
        self.position = Vec3(pos[0], pos[1], pos[2])
M
march3 已提交
51 52
        # 将摄像机位置设置为 x=0、y=1、z=0 的位置
        # camera.position = Vec3(pos[0], pos[1], pos[2])
三月三net's avatar
三月三net 已提交
53
        # self.position = Vec3(pos[0], pos[1], pos[2])
M
march3 已提交
54 55 56
        # 将摄像机的观察角度绕 x 轴旋转 45 度,绕 y 轴旋转 0 度,绕 z 轴旋转 0 度
        camera.rotation = Vec3(45, 90, 0)

三月三net's avatar
三月三net 已提交
57 58 59 60
        # self.gravity = 0
        # self.vspeed = 400
        # self.speed = 1000
        # self.mouse_sensitivity = Vec2(160, 160)
M
march3 已提交
61
        self.on_enable()
三月三net's avatar
三月三net 已提交
62
        # self.rotation_speed = 80
M
march3 已提交
63

M
march3 已提交
64 65 66 67 68 69
    def input(self, key):
        if key == "escape":
            if mouse.locked:
                self.on_disable()
            else:
                sys.exit()
M
march3 已提交
70
        return super().input(key)
M
march3 已提交
71

三月三net's avatar
三月三net 已提交
72 73

class Planet(Entity):
M
march3 已提交
74 75
    def __init__(self, body_view: BodyView):
        self.body_view = body_view
三月三net's avatar
三月三net 已提交
76 77
        # 旋转速度和大小成反比(未使用真实数据)
        self.rotspeed = 30000 / self.body_view.raduis  # random.uniform(1.0, 2.0)
M
march3 已提交
78 79 80
        self.rotMode = 'x'  # random.choice(["x", "y", "z"])
        self.name = body_view.name

M
march3 已提交
81
        pos = body_view.position * body_view.body.distance_scale * SCALE_FACTOR
M
march3 已提交
82 83
        scale = body_view.body.diameter * body_view.body.size_scale * SCALE_FACTOR

三月三net's avatar
三月三net 已提交
84
        if hasattr(body_view, "texture"):
三月三net's avatar
三月三net 已提交
85 86 87
            texture = load_texture(body_view.texture)
        else:
            texture = None
M
march3 已提交
88

三月三net's avatar
三月三net 已提交
89 90 91 92 93 94 95
        super().__init__(
            model="sphere",
            scale=scale,
            texture=texture,
            color=color.white,
            position=pos,
            rotation=(0, 0, 0))
三月三net's avatar
三月三net 已提交
96

M
march3 已提交
97
    def turn(self):
M
march3 已提交
98
        pos = self.body_view.position * SCALE_FACTOR
三月三net's avatar
三月三net 已提交
99

M
march3 已提交
100 101 102
        self.x = -pos[1]
        self.y = pos[2]
        self.z = pos[0]
M
march3 已提交
103

M
march3 已提交
104
        self.rotation_y -= self.rotspeed
M
march3 已提交
105

三月三net's avatar
三月三net 已提交
106 107 108 109 110 111 112 113 114 115 116 117
    def input(self, key):
        if key == "enter":
            self.fastMode = 1 - self.fastMode


class UrsinaView(BodyView):
    """
    ursina天体视图(天体效果展示用)
    """

    def __init__(self, body: Body):
        BodyView.__init__(self, body)
M
march3 已提交
118 119
        self.velocity = body.velocity

M
march3 已提交
120
        self.planet = Planet(self)
M
march3 已提交
121 122 123
        if body.has_rings:
            self.create_rings()

三月三net's avatar
三月三net 已提交
124 125 126 127
        if self.body.is_fixed_star:
            # 如果是恒星(如:太阳),自身会发光,则需要关闭灯光
            self.planet.set_light_off()

M
march3 已提交
128
    def create_rings(self):
三月三net's avatar
三月三net 已提交
129 130 131 132
        """
        创建星环(使用土星贴图)
        :return:
        """
三月三net's avatar
三月三net 已提交
133 134 135 136
        scale = 3 * self.body.diameter * self.body.size_scale * SCALE_FACTOR
        pos = self.planet.position
        self.ring = Entity(model="circle", texture='../textures/saturnRings.jpg', scale=scale, position=pos,
                           rotation=(70, 0, 0), double_sided=True)
三月三net's avatar
三月三net 已提交
137
        # 假设星环自身会发光
三月三net's avatar
三月三net 已提交
138
        self.ring.set_light_off()
三月三net's avatar
三月三net 已提交
139 140

    def update(self):
M
march3 已提交
141
        self.planet.turn()
三月三net's avatar
三月三net 已提交
142 143
        if hasattr(self, "light"):
            self.light.position = Vec3(self.planet.x, self.planet.y, self.planet.z)
三月三net's avatar
三月三net 已提交
144 145
        if hasattr(self, "ring"):
            self.ring.position = Vec3(self.planet.x, self.planet.y, self.planet.z)
三月三net's avatar
三月三net 已提交
146 147 148 149 150

    def appear(self):
        pass

    def disappear(self):
M
march3 已提交
151
        self.planet.disable()