[PYTHON] Erstellen Sie einen Sternenhimmel auf Unity aus einer Sternendatenbank (veröffentlicht)

Abschlusszeichnung

image.png

Von links

Der als Spielbildschirm gespielte ist wie folgt. </ s> Als WebGL-App veröffentlicht.

https://hibit-at.github.io/StarSphere/

Stellare Datenbank

Es scheint, dass es auf der Welt eine Sternendatenbank gibt. Wenn Sie diese also so wie sie ist als Kugel anordnen, können Sie ein realistisches Planetarium erstellen? Ich habe darüber nachgedacht und es versucht. Der Code des Skripts unten.

using System.Collections.Generic;
using UnityEngine;
using System.IO;

public class Reader : MonoBehaviour
{
    TextAsset csvFile;
    List<string[]> csvDatas = new List<string[]>();
    public Material[] _material;//Dieses Material muss im Voraus vorbereitet werden

    //Liste zum Ausmalen bestimmter Konstellationen
    List<string> Spring = new List<string> { "Arcturus" , "Spica" , "Denebola" };
    List<string> Summer = new List<string> { "Deneb", "Altair", "Vega" };
    List<string> Autumn = new List<string> { "Markab", "Sheat", "Algenib" , "Alpheratz" };
    List<string> Winter = new List<string> { "Capella", "Aldebaran", "Rigel", "Pollux" ,"Procyon" , "Sirius" };

    int Color(string target) //Eine Funktion, die eine Zahl zurückgibt, um die Konstellation einzufärben
    {
        foreach (string c in Spring) if (target == c) return 1;
        foreach (string c in Summer) if (target == c) return 2;
        foreach (string c in Autumn) if (target == c) return 3;
        foreach (string c in Winter) if (target == c) return 4;
        return 0;
    }

    void Start()
    {
        csvFile = Resources.Load("mdata") as TextAsset; //Geben Sie hier Ihre eigenen Daten zurück
        StringReader reader = new StringReader(csvFile.text);
        while (reader.Peek() != -1)
        {
            string line = reader.ReadLine();
            csvDatas.Add(line.Split(','));
        }

        foreach (string[] c in csvDatas)
        {
            int lon1 = int.Parse(c[3]);
            int lon2 = int.Parse(c[4]);
            float theta = lon1 * 15 + lon2 / 4;
            theta *= 2.0f * Mathf.PI / 360;
            int lat1 = int.Parse(c[7]);
            int lat2 = int.Parse(c[8]);
            float phi = lat1 + lat2 / 60;
            if (c[6] == "0") phi = -phi;
            phi *= 2.0f * Mathf.PI / 360;
            GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            sphere.transform.position = new Vector3(10 * Mathf.Cos(theta) * Mathf.Cos(phi),
                                                    10 * Mathf.Sin(phi),
                                                    10 * Mathf.Sin(theta) * Mathf.Cos(phi));
            float tokyu = float.Parse(c[10]);
            tokyu = 0.6f - tokyu / 10;
            if (tokyu < 0) tokyu = 0;
            sphere.transform.localScale = new Vector3(tokyu, tokyu, tokyu);
            sphere.GetComponent<Renderer>().material = _material[Color(c[2])];
        }
    }
}

Wenn Sie dies an ein geeignetes Spielobjekt anhängen, werden zu Beginn des Spiels etwa 3.000 Sterne (Kugeln) in die Szene gezeichnet. Wenn Sie es tatsächlich versuchen, ist eine Vorbehandlung erforderlich, wie später beschrieben.

Vordatenverarbeitung

Es verwendet die Daten aus der oben in hip_lite_major.csv erwähnten Datenbank (ca. 3.000 Zeilen), enthält jedoch nicht die Namen der Sterne. Für alle Sterne [Hippalcos Star Chart](https://ja.wikipedia.org/wiki/%E3%83%92%E3%83%83%E3%83%91%E3%83%AB%E3% Es scheint, dass die Zahlen (HIP-Nummern) in der Tabelle angegeben sind. 82% B3% E3% 82% B9% E6% 98% 9F% E8% A1% A8) (Wow!), Aber natürlich sind die Namen darin angegeben. Es gibt nur wenige prominente Sterne, die angebracht werden können. Die Daten sind separat in "hip_proper_name.csv" organisiert, müssen jedoch als sogenannte relationale Daten kombiniert werden. Glücklicherweise ist die HIP-Nummer der Primärschlüssel, sodass der Vorgang schnell vonstatten geht.

Die Vorverarbeitung hier ist schnell mit Python und "Pandas" erledigt.

import pandas as pd
data = pd.read_csv('hip_proper_name.csv',header=None)
detail = pd.read_csv('hip_lite_major.csv',header=None)
mdata = pd.merge(detail,data,on=0,how="left")
mdata.to_csv('mdata.csv',header=None)

Dadurch wird eine "mdata.csv" erstellt, die eine Zusammenführung der beiden ist. Fügen Sie diese also in Ihr Unity-Projekt ein.

Außerdem werden die Materialeinstellungen auf der Unity-Seite manuell vorgenommen. Wenn Sie Ihr Bestes geben, können Sie es in ein Skript schreiben, aber Sie können hier wirklich Kompromisse eingehen.

image.png

Erstellen Sie ein Konstellationsfarbmaterial und legen Sie es im Slot "GameObject" -Material fest, um das Skript anzuhängen.

Erklärung des Quellcodes

    //Liste zum Ausmalen bestimmter Konstellationen
    List<string> Spring = new List<string> { "Arcturus" , "Spica" , "Denebola" };
    List<string> Summer = new List<string> { "Deneb", "Altair", "Vega" };
    List<string> Autumn = new List<string> { "Markab", "Sheat", "Algenib" , "Alpheratz" };
    List<string> Winter = new List<string> { "Capella", "Aldebaran", "Rigel", "Pollux" ,"Procyon" , "Sirius" };

Der Name der Konstellation (es ist keine Konstellation, sondern etwas, das mehrere Sterne überspannt, aber ich kann keinen anderen guten Namen finden, also nenne ich es eine Konstellation) steht nicht auf der CSV, daher müssen Sie ihn selbst vorbereiten Es gibt. Machen Sie eine Liste jeder Konstellation.

Informationen zum Lesen der CSV-Datei finden Sie unter https://note.com/macgyverthink/n/n83943f3bad60. Vielen Dank.

Aus jeder Zeile von csv berechnen wir den Winkel und die Skalierung.

Der Winkel wird aus dem roten Längengrad (Stunden, Minuten, Sekunden) und dem roten Breitengrad (Grad, Minuten, Sekunden) in der Datenbank berechnet. Es ist ein wenig kompliziert, weil es Grad, Minuten und Sekunden sind, aber der Winkel des roten Breitengrads $ \ phi $

\ phi = Grad + \ frac {Minuten} {60} + \ frac {Sekunden} {3600}

Sie können herausfinden, dass es ist. In Bezug auf das rote Sutra $ \ theta $ sind es ** Stunden **, Minuten, Sekunden, die nicht herauskamen, selbst wenn ich es überprüft habe, aber der Punkt ist, dass 360 Grad in 24 geteilt sind, also ** Es wird 15 Grad ** pro Stunde sein. Sie können also sehen, dass Sie der obigen Formel $ 15 $ hinzufügen können.

\ theta = Stunde * 15 + \ frac {Minuten} {4} + \ frac {Sekunden} {240}

Sie können mit den oben genannten berechnen. Beachten Sie, dass die Drehung von Unity in Bogenmaßeinheiten erfolgt und das Koordinatensystem linkshändig ist.

            theta *= 2.0f * Mathf.PI / 360;
(Weggelassen)
            phi *= 2.0f * Mathf.PI / 360;
(Weggelassen)
            sphere.transform.position = new Vector3(10 * Mathf.Cos(theta) * Mathf.Cos(phi),
                                                    10 * Mathf.Sin(phi),
                                                    10 * Mathf.Sin(theta) * Mathf.Cos(phi));

Sie können jeden Stern an den richtigen Koordinaten mit platzieren. Zusätzlich wird der Helligkeitsunterschied für jede Klasse durch die Größe der Kugel angezeigt.

            float tokyu = float.Parse(c[10]);
            tokyu = 0.6f - tokyu / 10;
            if (tokyu < 0) tokyu = 0;
            sphere.transform.localScale = new Vector3(tokyu, tokyu, tokyu);

Dies gibt Ihnen das Gefühl eines Sternenhimmels.

Was du machen willst

Da es als Daten zu Unity verarbeitet werden kann, kann ein interaktives Planetarium realisiert werden, wenn ein Mechanismus erstellt wird, mit dem die angezeigten Sterne manipuliert und die Konstellationslinien entstehen können. Wenn Sie es mit Quest bauen, können Sie anscheinend auch im Freien ein eigenständiges und einfaches Planetarium erstellen (und jedes Mal, wenn Sie das Headset entfernen, vom tatsächlichen Sternenhimmel-Shobo enttäuscht sein). Ich würde es gerne versuchen, wenn ich Zeit und Energie habe.

Hinzugefügt (veröffentlicht)

Danach bat ich einen Freund, der mit astronomischer Beobachtung vertraut ist, sie zu sehen, passte Größe und Farbe an und veröffentlichte sie als WebGL-Anwendung. Die neueste Version des Codes.

using System.Collections.Generic;
using UnityEngine;
using System.IO;

public class Reader : MonoBehaviour
{
    TextAsset csvFile;
    List<string[]> csvDatas = new List<string[]>();
    public Material[] _material;

    List<string> Spring = new List<string> { "Arcturus" , "Spica" , "Denebola" };
    List<string> Summer = new List<string> { "Deneb", "Altair", "Vega" };
    List<string> Autumn = new List<string> { "Markab", "Sheat", "Algenib" , "Alpheratz" };
    List<string> Winter = new List<string> { "Capella", "Aldebaran", "Rigel", "Pollux" ,"Procyon" , "Sirius" };

    int Colorization(string target)
    {
        foreach (string c in Spring) if (target == c) return 1;
        foreach (string c in Summer) if (target == c) return 2;
        foreach (string c in Autumn) if (target == c) return 3;
        foreach (string c in Winter) if (target == c) return 4;
        return 0;
    }

    Color Spectrum(string s)
    {
        if(s == "")
        {
            return new Color(.5f, .5f, .5f, 1);
        }
        char c = s[0];
        if(c == 'O')
        {
            return new Color(.3f, .3f, .8f,1);
        }
        else if (c == 'B')
        {
            return new Color(.3f, .3f, .8f, 1);
        }
        else if (c == 'A')
        {
            return new Color(.5f, .5f, 1, 1);
        }
        else if (c == 'F')
        {
            return new Color(1, 1, 1, 1);
        }
        else if (c == 'G')
        {
            return new Color(.8f, .8f, .4f, 1);
        }
        else if (c == 'K')
        {
            return new Color(.8f, .4f, 0, 1);
        }
        else if(c == 'M')
        {
            return new Color(.4f, 0, 0, 0);
        }
        else
        {
            return new Color(.5f, .5f, .5f, 1);
        }
    }
    
    void Start()
    {
        csvFile = Resources.Load("mdata") as TextAsset;
        StringReader reader = new StringReader(csvFile.text);
        while (reader.Peek() != -1)
        {
            string line = reader.ReadLine();
            csvDatas.Add(line.Split(','));
        }

        foreach (string[] c in csvDatas)
        {
            int lon1 = int.Parse(c[3]);
            int lon2 = int.Parse(c[4]);
            float theta = lon1 * 15 + lon2 / 4;
            theta *= 2.0f * Mathf.PI / 360;
            int lat1 = int.Parse(c[7]);
            int lat2 = int.Parse(c[8]);
            float phi = lat1 + lat2 / 60;
            if (c[6] == "0") phi = -phi;
            phi *= 2.0f * Mathf.PI / 360;
            GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            sphere.transform.position = new Vector3(10 * Mathf.Cos(theta) * Mathf.Cos(phi),
                                                    10 * Mathf.Sin(phi),
                                                    10 * Mathf.Sin(theta) * Mathf.Cos(phi));
            float tokyu = float.Parse(c[10]);
            tokyu = 0.3f - tokyu / 20;
            if (tokyu < 0) tokyu = 0;
            sphere.transform.localScale = new Vector3(tokyu, tokyu, tokyu);
            MeshRenderer r = sphere.GetComponent<MeshRenderer>();
            r.material = _material[0];
            r.material.EnableKeyword("_EMISSION");
            Color StarColor = Spectrum(c[11]) * tokyu / 0.3f;
            if (float.Parse(c[10]) <= 1.5f)
            {
                r.material.SetColor("_EmissionColor", StarColor * .3f);
            }
            
            //sphere.GetComponent<Renderer>().material = _material[Colorization(c[2])];
        }
    }
}

Die Farbe des Sterns ist [Spektrumklassifizierung](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%9A%E3%82%AF%E3%83%88%E3%83% Es ist assoziiert mit AB% E5% 88% 86% E9% A1% 9E). Da es durch Buchstaben wie O und K klassifiziert ist, wird es mit der if-Anweisung verarbeitet. Die Farbe wird angepasst, indem sie mit r.material.SetColor (" _EmissionColor ", StarColor * .3f); auf die Emissionsfarbe des Materials eingestellt wird.

Das GitHub-Repository befindet sich hier.

Was ich machen möchte 2

  • VR-Anwendung
  • Anzeige der Konstellationslinie

Recommended Posts

Erstellen Sie einen Sternenhimmel auf Unity aus einer Sternendatenbank (veröffentlicht)
Erstellen Sie eine Python3-Umgebung unter CentOS7
Erstellen Sie mit Cloud9 (jupyter miniconda python3) eine Lernumgebung für "Deep Learning von Grund auf neu".
Ich habe ein WebAPI gemacht! Erstellen einer Umgebung aus Django Rest Framework 1 mit EC2
Erstellen Sie einen Pypi-Cache-Server auf QNAP
Erstellen Sie eine Python-Umgebung unter MacOS (Catallina)
Erstellen Sie einen einfachen WebDAV-Server unter Linux
Machen Sie Unity Accelerator zu einem Dienst unter Linux
Erstellen Sie einen Samba-Server unter Arch Linux
Lassen Sie uns einen WEB-Server mit Chromebook einrichten
Erstellen Sie eine Python + OpenCV-Umgebung in Cloud9