//画面を更新する(球体地図) public void updateScreen2() { double hinode_keido, hinoiri_keido, asayake, higure; int hinoiriX = 0, hinodeX = 0; int asayakeX = 0, higureX = 0; double x, y; double halfPI = Math.PI / 2.0; //double scrDist = (scrWidth / 2.0) / Math.Tan(scrAngle / 180.0 * Math.PI); //if (screen == null | screen2 == null) return; //イメージを初期化 Color opaque = new Color(0, 0, 0, 0); for (int i = 0; i < shadow.width; i++) { for (int j = 0; j < shadow.height; j++) { shadow.SetPixel(i, j, opaque); } } EquatorialCoordinate sun = new EquatorialCoordinate(); EquatorialCoordinate moon = new EquatorialCoordinate(); double[] result = new double[3]; double[] result2 = new double[3]; double[] location = new double[2]; double asc = 0.0; double dec = 0.0; double moonasc = 0.0; double moondec = 0.0; try { SunAndMoon.getSunRightAscension(utc, result); sun.setRightAscension(result[0]); sun.setCelestialDeclination(result[1]); sun.setDistance(result[2]); asc = result[0]; //赤経 dec = result[1]; //赤緯 SunAndMoon.getMoonRightAscension(utc, result); moon.setRightAscension(result[0]); moon.setCelestialDeclination(result[1]); moon.setDistance(result[2]); moonasc = result[0]; moondec = result[1]; } catch (Exception) { Debug.Log("Exception1 "); return; } double phai0 = Almanac.getGreenidgeSiderealTime(utc);//グリニッジ恒星時 //恒星時をもとに、背景の回転を行う(恒星時は春分点の時角) Material skybox = RenderSettings.skybox; skybox.SetFloat("_Rotation", (float)-phai0);//時角のマイナス方向に回転。skyboxのマテリアルは左右が逆 //太陽位置計算(orbiterと同じコード) { double Theta = phai0 - asc; if (Theta < 0) { Theta += 360.0; } double DegToRad = Math.PI / 180; double denominator = (Math.Sin(dec * DegToRad) * Math.Cos(90.0 * DegToRad) - Math.Cos(dec * DegToRad) * Math.Sin(90.0 * DegToRad) * Math.Cos(Theta * DegToRad)); double A = Math.Atan((-Math.Cos(dec * DegToRad) * Math.Sin(Theta * DegToRad)) / denominator); double h = Math.Asin(Math.Sin(dec * DegToRad) * Math.Sin(90.0 * DegToRad) + Math.Cos(dec * DegToRad) * Math.Cos(90.0 * DegToRad) * Math.Cos(Theta * DegToRad)); A = A / DegToRad; h = h / DegToRad; //Arctanの象限を検討せよ if (denominator > 0) { //何故か解説書とは逆だが、分母が正の時に180度加算して象限を変える必要がある A += 180.0; } Vector3 sunvector = new Vector3(1.0f, 0.0f, 0.0f); sunvector = Quaternion.Euler(0.0f, 0.0f, (float)h) * sunvector; sunvector = Quaternion.Euler(0.0f, (float)A, 0.0f) * sunvector; float ratio = 1500.0f / sunvector.magnitude; sunvector *= ratio; GameObject game = GameObject.Find("Directional Light"); if (game != null) { game.transform.position = sunvector; Vector3 forward = sunvector; forward.Normalize(); game.transform.forward = -forward; } } //日の出・日の入りの同時線を描く double dist = sun.getDistance(); double parallax = SunAndMoon.getSunParallax(dist);//太陽視差 double k = SunAndMoon.getSunriseAltitude(SunAndMoon.getSunDiameter(dist), 0.0, SunAndMoon.refraction, parallax); double celestialdeclination = sun.getCelestialDeclination(); for (int i = -90; i < 90; i++) { //緯度を取得 double latitude = i;//getLatitudeFromY(Yequator - i); //緯度を元に時角を計算する double jikaku = SunAndMoon.getTimeAngle(k, celestialdeclination, latitude); if (!Double.IsNaN(jikaku))//時角がNaNでない { hinode_keido = SunAndMoon.reviseAngle(-jikaku + sun.getRightAscension() - phai0); hinoiri_keido = SunAndMoon.reviseAngle(jikaku + sun.getRightAscension() - phai0); // hinodeX =(int)getXfromLongitude(hinode_keido); // hinoiriX = (int)getXfromLongitude(hinoiri_keido);//昼側か調べる drawShadowTexture(hinode_keido, latitude, Color.white); drawShadowTexture(hinoiri_keido, latitude, Color.white); } } //輪郭の描画 VesselElements ve = new VesselElements(sun, moon, utc); SolarEclipse.getCrossPoint(ve, result, result2); double maxQ = SolarEclipse.getPenumbralQ(ve, result); double minQ = SolarEclipse.getPenumbralQ(ve, result2); //Debug.Log("MaxQ = " + maxQ + " minQ = " + minQ); //月位置計算(orbiterと同じコード) { double Theta = phai0 - moonasc; if (Theta < 0) { Theta += 360.0; } double DegToRad = Math.PI / 180; double denominator = (Math.Sin(moondec * DegToRad) * Math.Cos(90.0 * DegToRad) - Math.Cos(moondec * DegToRad) * Math.Sin(90.0 * DegToRad) * Math.Cos(Theta * DegToRad)); double A = Math.Atan((-Math.Cos(moondec * DegToRad) * Math.Sin(Theta * DegToRad)) / denominator); double h = Math.Asin(Math.Sin(moondec * DegToRad) * Math.Sin(90.0 * DegToRad) + Math.Cos(moondec * DegToRad) * Math.Cos(90.0 * DegToRad) * Math.Cos(Theta * DegToRad)); A = A / DegToRad; h = h / DegToRad; //Arctanの象限を検討せよ if (denominator > 0) { //何故か解説書とは逆だが、分母が正の時に180度加算して象限を変える必要がある A += 180.0; } Vector3 sunvector = new Vector3(1.0f, 0.0f, 0.0f); sunvector = Quaternion.Euler(0.0f, 0.0f, (float)h) * sunvector; sunvector = Quaternion.Euler(0.0f, (float)A, 0.0f) * sunvector; float ratio = (float)(moon.getDistance() * Constants.AUde * 3.16f) / sunvector.magnitude; sunvector *= ratio; // // Debug.Log("moondist = " + moon.getDistance()); GameObject game = GameObject.Find("Moon"); if (game != null) { game.transform.position = sunvector; } } /* Vector3 moonPos = new Vector3((float)ve.getX0(), (float)ve.getY0(), (float)ve.getZ0()); * moonPos.Normalize(); * moonPos *= 20; * GameObject moonobj = GameObject.Find("Moon"); * * if (moonobj!= null) * { * moonobj.transform.position = moonPos; * } */ //半影の描画 if (Double.IsNaN(maxQ) && Double.IsNaN(minQ)) { double first_longitude = Double.NaN; double first_latitude = Double.NaN; double last_longitude = Double.NaN; double last_latitude = Double.NaN; for (double i = 0.0; i <= 360.0; i += 0.2) { SolarEclipse.getPenumbralOutline(ve, i, result); if (Double.IsNaN(result[0]) | Double.IsNaN(result[1]) | Double.IsNaN(result[2])) { continue; //NaNが含まれていたらスキップする } if (first_longitude == double.NaN | first_latitude == double.NaN) { first_longitude = result[0]; first_latitude = result[1]; } last_longitude = result[0]; last_latitude = result[1]; Coordinate.transformICRStoGCS(ve, result, location); drawShadowTexture(location[0], location[1], Color.red); } //Debug.Log(first_longitude + ":" + first_latitude + "::" + last_longitude + ":" + last_latitude); } else if (!Double.IsNaN(maxQ) && !Double.IsNaN(minQ)) { double first_x = double.NaN; double first_y = double.NaN; double first_z = double.NaN; double last_x = double.NaN; double last_y = double.NaN; double last_z = double.NaN; if ((maxQ - minQ) >= 0.0) { maxQ -= 360.0; } SolarEclipse.getPenumbralOutline(ve, maxQ, result); Coordinate.transformICRStoGCS(ve, result, location); //Debug.Log("MaxQ :" + location[0] + ":" + location[1]+ ":" + maxQ); SolarEclipse.getPenumbralOutline(ve, minQ, result); Coordinate.transformICRStoGCS(ve, result, location); //Debug.Log("MinQ :" + location[0] + ":" + location[1] + ":" + minQ); /* * //maxQが通常の計算でNaNとなる場合に備えて、強制的に描画する。 * SolarEclipse.getPenumbralOutline(ve, maxQ, result); * result[2] = -0.01;//強制的に基準面に設定する * Coordinate.transformICRStoGCS(ve, result, location); * drawShadowTexture(location[0], location[1], Color.black); */ for (double i = maxQ /*Math.Ceiling(maxQ)*/; i < minQ; i += 0.2) { SolarEclipse.getPenumbralOutline(ve, i, result); if (Double.IsNaN(result[0]) | Double.IsNaN(result[1]) | Double.IsNaN(result[2])) { continue; //NaNが含まれていたらスキップする } if (Double.IsNaN(first_x) | Double.IsNaN(first_y) | Double.IsNaN(first_z)) { first_x = result[0]; first_y = result[1]; first_z = result[2]; } last_x = result[0]; last_y = result[1]; last_z = result[2]; Coordinate.transformICRStoGCS(ve, result, location); drawShadowTexture(location[0], location[1], Color.red); } { SolarEclipse.getPenumbralOutline(ve, minQ, result); if (!Double.IsNaN(result[0]) & !Double.IsNaN(result[1]) & !Double.IsNaN(result[2])) { Coordinate.transformICRStoGCS(ve, result, location); last_x = result[0]; last_y = result[2]; last_z = result[1]; drawShadowTexture(location[0], location[1], Color.red); } } //drawClosingLine2(ve, first_x, first_y, first_z, last_x, last_y, last_z); //Debug.Log(first_longitude + ":" + first_latitude + "::" + last_longitude + ":" + last_latitude); /* * //minQが通常の計算でNaNとなる場合に備えて、強制的に描画する。 * SolarEclipse.getPenumbralOutline(ve, minQ, result); * result[2] = -0.01;//強制的に基準面に設定する * Coordinate.transformICRStoGCS(ve, result, location); * drawShadowTexture(location[0], location[1], Color.red); */ } //本影の描画 for (int i = 0; i <= 360; i += 5) { SolarEclipse.getUmbralOutline(ve, (double)i, result); if (Double.IsNaN(result[0]) | Double.IsNaN(result[1]) | Double.IsNaN(result[2])) { continue; //NaNが含まれていたらスキップする } Coordinate.transformICRStoGCS(ve, result, location); drawShadowTexture(location[0], location[1], Color.black); } GameObject earthobj = GameObject.Find("perfectsphere"); Material[] mats = earthobj.GetComponent <Renderer>().materials; Debug.Log("elements =" + mats.Length); mats[0].SetTexture("_MainTex", (Texture)shadow); //mats[1].SetTexture("_EmissionMap", shadow); //repaint(); }
public void drawLines() { //テクスチャ初期化 Color opaque = new Color(0, 0, 0, 0); for (int i = 0; i < shadow.width; i++) { for (int j = 0; j < shadow.height; j++) { shadow.SetPixel(i, j, opaque); } } EquatorialCoordinate sun = new EquatorialCoordinate(); EquatorialCoordinate moon = new EquatorialCoordinate(); double[] result = new double[3]; double[] result2 = new double[3]; double[] location = new double[2]; double asc = 0.0; double dec = 0.0; double moonasc = 0.0; double moondec = 0.0; try { SunAndMoon.getSunRightAscension(utc, result); sun.setRightAscension(result[0]); sun.setCelestialDeclination(result[1]); sun.setDistance(result[2]); asc = result[0]; //赤経 dec = result[1]; //赤緯 SunAndMoon.getMoonRightAscension(utc, result); moon.setRightAscension(result[0]); moon.setCelestialDeclination(result[1]); moon.setDistance(result[2]); moonasc = result[0]; moondec = result[1]; } catch (Exception) { Debug.Log("Exception1 "); return; } double phai0 = Almanac.getGreenidgeSiderealTime(utc);//グリニッジ恒星時 //太陽位置を計算してライトの位置と向きを変更する { //恒星時をもとに、背景の回転を行う(恒星時は春分点の時角) Material skybox = RenderSettings.skybox; skybox.SetFloat("_Rotation", (float)-phai0);//時角のマイナス方向に回転。skyboxのマテリアルは左右が逆 //赤緯・赤経は北極から見て時計回り。自覚、恒星時は反時計回り。時角に合わせて計算する //float ramda = -(float)((-asc + phai0) * DegToRad);これを書き換えて下の式になる float ramda = (float)((asc - phai0) * DegToRad); float psy = (float)(dec * DegToRad); float sundistance = 400; float x = Mathf.Cos(psy) * Mathf.Cos(ramda) * sundistance; float y = Mathf.Cos(psy) * Mathf.Sin(ramda) * sundistance; float z = Mathf.Sin(psy) * sundistance; GameObject light = GameObject.Find("Directional Light"); Vector3 sunpos = light.transform.position; sunpos.Set(x, z, y); light.transform.position = sunpos; sunpos.Normalize(); sunpos *= -1; light.transform.forward = sunpos; } /* * //日の出・日の入りの同時線を描く * { * double dist = sun.getDistance(); * double parallax = SunAndMoon.getSunParallax(dist);//太陽視差 * double k = SunAndMoon.getSunriseAltitude(SunAndMoon.getSunDiameter(dist), 0.0, SunAndMoon.refraction, parallax); * double celestialdeclination = sun.getCelestialDeclination(); * * for (int i = -90; i < 90; i++) * { * //緯度を取得 * double latitude = i;//getLatitudeFromY(Yequator - i); * * //緯度を元に時角を計算する * double jikaku = SunAndMoon.getTimeAngle(k, celestialdeclination, latitude); * * if (!Double.IsNaN(jikaku))//時角がNaNでない * { * double hinode_keido = SunAndMoon.reviseAngle(-jikaku + sun.getRightAscension() - phai0); * double hinoiri_keido = SunAndMoon.reviseAngle(jikaku + sun.getRightAscension() - phai0); * // hinodeX =(int)getXfromLongitude(hinode_keido); * // hinoiriX = (int)getXfromLongitude(hinoiri_keido);//昼側か調べる * drawShadowTexture(hinode_keido, latitude, Color.white); * drawShadowTexture(hinoiri_keido, latitude, Color.white); * } * } * } */ //輪郭の描画 //ベッセル数 VesselElements ve = new VesselElements(sun, moon, utc); SolarEclipse.getCrossPoint(ve, result, result2); //月影と地球外円との交点を調べる double maxQ = SolarEclipse.getPenumbralQ(ve, result); double minQ = SolarEclipse.getPenumbralQ(ve, result2); //Debug.Log("MaxQ = " + maxQ + " minQ = " + minQ); //半影の描画 if (Double.IsNaN(maxQ) && Double.IsNaN(minQ)) { //交点が存在しない場合。月影がすべて地球上に投射されている。 double first_longitude = Double.NaN; double first_latitude = Double.NaN; double last_longitude; double last_latitude; Color gray = new Color(0, 0, 0, 0.4f); //初期の点 SolarEclipse.getPenumbralOutline(ve, 0.0, result); Coordinate.transformICRStoGCS(ve, result, location); last_longitude = location[0]; last_latitude = location[1]; bool fill = true; for (double i = 1.0; i <= 360.0; i += 1.0) { SolarEclipse.getPenumbralOutline(ve, i, result2); if (Double.IsNaN(result2[0]) | Double.IsNaN(result2[1]) | Double.IsNaN(result2[2])) { fill = false; continue;//NaNが含まれていたらスキップする } Coordinate.transformICRStoGCS(ve, result2, location); // drawShadowTexture(location[0], location[1], gray); //Debug.Log("i=" + i + ":" +location[0] + ":" + location[1]); drawOutline(last_longitude, last_latitude, location[0], location[1], Color.red); last_longitude = location[0]; last_latitude = location[1]; } if (fill) { fillShadow(last_longitude - 2, last_latitude, shadow, gray); } /* * byte[] pngData = shadow.EncodeToPNG(); // pngのバイト情報を取得. * * // ファイルダイアログの表示. * string filePath = EditorUtility.SaveFilePanel("Save Texture", "", shadow.name + ".png", "png"); * * if (filePath.Length > 0) * { * // pngファイル保存. * File.WriteAllBytes(filePath, pngData); * } */ //Debug.Log(first_longitude + ":" + first_latitude + "::" + last_longitude + ":" + last_latitude); } else if (!Double.IsNaN(maxQ) && !Double.IsNaN(minQ))//交点が存在する { double first_x = double.NaN; double first_y = double.NaN; double first_z = double.NaN; double last_x = double.NaN; double last_y = double.NaN; double last_z = double.NaN; Color gray = new Color(0, 0, 0, 0.4f); if ((maxQ - minQ) >= 0.0) { maxQ -= 360.0; } SolarEclipse.getPenumbralOutline(ve, maxQ, result); Coordinate.transformICRStoGCS(ve, result, location); //Debug.Log("MaxQ :" + location[0] + ":" + location[1]+ ":" + maxQ); SolarEclipse.getPenumbralOutline(ve, minQ, result); Coordinate.transformICRStoGCS(ve, result, location); //Debug.Log("MinQ :" + location[0] + ":" + location[1] + ":" + minQ); /* * //maxQが通常の計算でNaNとなる場合に備えて、強制的に描画する。 * SolarEclipse.getPenumbralOutline(ve, maxQ, result); * result[2] = -0.01;//強制的に基準面に設定する * Coordinate.transformICRStoGCS(ve, result, location); * drawShadowTexture(location[0], location[1], Color.black); */ for (double i = maxQ /*Math.Ceiling(maxQ)*/; i < minQ; i += 0.2) { SolarEclipse.getPenumbralOutline(ve, i, result); if (Double.IsNaN(result[0]) | Double.IsNaN(result[1]) | Double.IsNaN(result[2])) { continue; //NaNが含まれていたらスキップする } if (Double.IsNaN(first_x) | Double.IsNaN(first_y) | Double.IsNaN(first_z)) { first_x = result[0]; first_y = result[1]; first_z = result[2]; } last_x = result[0]; last_y = result[1]; last_z = result[2]; Coordinate.transformICRStoGCS(ve, result, location); drawShadowTexture(location[0], location[1], gray); } { SolarEclipse.getPenumbralOutline(ve, minQ, result); if (!Double.IsNaN(result[0]) & !Double.IsNaN(result[1]) & !Double.IsNaN(result[2])) { Coordinate.transformICRStoGCS(ve, result, location); last_x = result[0]; last_y = result[2]; last_z = result[1]; drawShadowTexture(location[0], location[1], gray); } } } //本影の描画 for (int i = 0; i <= 360; i += 5) { SolarEclipse.getUmbralOutline(ve, (double)i, result); if (Double.IsNaN(result[0]) | Double.IsNaN(result[1]) | Double.IsNaN(result[2])) { continue; //NaNが含まれていたらスキップする } Coordinate.transformICRStoGCS(ve, result, location); drawShadowTexture(location[0], location[1], Color.black); } // shadow.Apply(); }