From the left
--Green Spring Triangle --Red Summer Triangle --Blue winter diamond --Purple autumn quadrilateral
The one played as a game screen is as follows. </ s>
Released as a WebGL app.
https://hibit-at.github.io/StarSphere/
It seems that there is a stellar database in the world, so if you arrange this as a sphere as it is, you can make a realistic planetarium? I thought about it and tried it. Below is the script code.
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class Reader : MonoBehaviour
{
TextAsset csvFile;
List<string[]> csvDatas = new List<string[]>();
public Material[] _material;//This material requires advance preparation
//List for coloring specific constellations
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) //A function that returns a number to color the constellations
{
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; //Return your own data here
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])];
}
}
}
If you attach this to an appropriate game object, about 3,000 stars (spheres) will be drawn in the scene at the start of the game. If you actually try to do it, some pretreatment is required as described later.
I use the data from the database mentioned above in hip_lite_major.csv
(about 3,000 rows), but it doesn't contain the names of the stars. For all stars [Hipparcos Catalog](https://ja.wikipedia.org/wiki/%E3%83%92%E3%83%83%E3%83%91%E3%83%AB%E3% It seems that the number (HIP number) is given by the table 82% B3% E3% 82% B9% E6% 98% 9F% E8% A1% A8) (Wow!), But of course the name is given in it. There are only a few prominent stars that can be attached. The data is organized separately in hip_proper_name.csv
, but they need to be so-called relational combined. Fortunately, the HIP number is the primary key, so the process is quick.
The pre-processing around here is done quickly with python and pandas
.
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)
This will create a mdata.csv
that is a merge of the two, so put this in your Unity project.
Also, material settings are done manually on the Unity side. If you do your best, you can write it in a script, but you can compromise around here.
Create a material with the color of the constellation and set it in the Material slot of the GameObject
to attach the script.
//List for coloring specific constellations
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" };
The name of the constellation (it's not a constellation but something that straddles multiple stars, but I can't find any other good name, so I'll call it a constellation) is not on the csv, so you need to prepare it yourself. There is. List each constellation.
For how to read the csv file, I referred to https://note.com/macgyverthink/n/n83943f3bad60 entirely. Thank you very much.
From each line of csv, we will calculate the angle and scale.
The angle is calculated from the right ascension (hours, minutes, seconds) and declination (degrees, minutes, seconds) in the database. It's a bit confusing because it's degrees, minutes, and seconds, but the declination angle $ \ phi $ is
You can find out that it is. About RA $ \ theta $, it is ** hours **, minutes, seconds, which did not come out even if I checked it, but the point is that 360 degrees is divided into 24, so ** It will be 15 degrees ** per hour. So you can see that you can add $ 15 $ to the above formula.
You can calculate with the above.
Note that Unity's Rotate
is in radians and the coordinate system is left-handed.
theta *= 2.0f * Mathf.PI / 360;
(Omitted)
phi *= 2.0f * Mathf.PI / 360;
(Omitted)
sphere.transform.position = new Vector3(10 * Mathf.Cos(theta) * Mathf.Cos(phi),
10 * Mathf.Sin(phi),
10 * Mathf.Sin(theta) * Mathf.Cos(phi));
You can place each star at the correct coordinates with. In addition, the difference in brightness for each grade is shown by the size of the sphere.
float tokyu = float.Parse(c[10]);
tokyu = 0.6f - tokyu / 10;
if (tokyu < 0) tokyu = 0;
sphere.transform.localScale = new Vector3(tokyu, tokyu, tokyu);
This will give you a feeling of a starry sky.
Since it can be handled as data on Unity, an interactive planetarium can be realized if a mechanism is created that allows the displayed stars to be manipulated and the constellation lines to emerge. If you build it with Quest, it seems that you can do something like a stand-alone and easy planetarium (and disappointed with the real starry sky shobo every time you remove the headset) even outdoors. I would like to try it if I have the time and energy.
After that, I asked a friend who is familiar with astronomical observation to see it, adjusted the size and color, and released it as a WebGL application. The latest version of the code.
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])];
}
}
}
The color of the star is [Spectrum Classification](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%9A%E3%82%AF%E3%83%88%E3%83% It is associated with AB% E5% 88% 86% E9% A1% 9E). Since it is classified by letters such as O and K, it is processed by if statement. The color is adjusted by setting it to the emission color of the material with r.material.SetColor ("_EmissionColor", StarColor * .3f);
.
The GitHub repository will be here.
--VR application --Display of constellation lines
Recommended Posts