# -*- 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) / 2
            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, repeat=1):
    verts = []
    tris = []
    uvs = []

    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
        # create vertices for outer radius
        outer_x = x * outer_radius
        outer_y = y * outer_radius

        if i % int(subdivisions / repeat) == 0:
            verts.append((inner_x, inner_y, 0))
            verts.append((outer_x, outer_y, 0))
            uvs.append((0.999, 0.0))
            uvs.append((0.999, 0.999))
            verts.append((inner_x, inner_y, 0))
            verts.append((outer_x, outer_y, 0))
            uvs.append((0.001, 0.0))
            uvs.append((0.001, 0.999))
        else:
            verts.append((inner_x, inner_y, 0))
            verts.append((outer_x, outer_y, 0))
            # create uvs
            u = angle * repeat / 360 % 1
            uvs.append((u, 0.0))
            uvs.append((u, 0.999))

        # 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 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'
    textureAsteroids = '../../textures/asteroids.png'

    # 创建球体
    # 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)
    # entity = Entity(model=torus, texture=textureRings, rotation=(0, 0, 0), double_sided=True)

    # torus = create_torus(1.5, 3, 64)
    # entity = Entity(model=torus, texture=textureRings, rotation=(85, 0, 0), double_sided=True)

    body_torus = create_torus(9, 10, 64)
    entities = Entity(model=body_torus, texture=textureAsteroids, rotation=(85, 0, 0), double_sided=True)
    entities.set_light_off()

    EditorCamera()
    app.run()
