開発環境 |
Microsoft Visual C# 2010 Express (SP1) |
実行環境 |
Microsoft Windows XP Home Edition (SP3) |
プロジェクトの種類 |
Windows Game (4.0) |
プロジェクト名 |
AstroSim1 |
Game1.cs
/*
* 太陽年を春分点の平均回帰年とし、365.24219日(365d5h48m45s)を採用する。
* 黄道傾斜角(地球の赤道傾斜角)を23deg26m21.406s(=84381.406s) 2000/01/01 12:00(UT)とする。
*/
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace AstroSim1
{
class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch sprite;
SpriteFont font;
BasicEffect effect;
VertexBuffer vertexBuffer;
//IndexBuffer indexBuffer;
const double au = 149597870700; // 天文単位(m)
const double Sr = 1392000 / 2; // 太陽の半径(km)
const double solarYear = 365.24219; // 太陽年(day)
const double obliquity = 84381.406; // 黄道傾斜角(degsec)
const double siderealDay = 86164.091; // 恒星日(s)
float camDist = (float)(au * 3);
float camLat = 0;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
graphics.PreferredBackBufferWidth = 1280;
graphics.PreferredBackBufferHeight = 720;
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void LoadContent()
{
sprite = new SpriteBatch(GraphicsDevice);
font = Content.Load<SpriteFont>("SpriteFont1");
effect = new BasicEffect(GraphicsDevice);
effect.VertexColorEnabled = true;
//effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45),
// GraphicsDevice.Viewport.AspectRatio, (float)au, (float)(au * 5));
effect.Projection = Matrix.CreateOrthographic(
camDist * GraphicsDevice.Viewport.AspectRatio, camDist, (float)au, (float)(au * 5));
VertexPositionColor[] vertices = new VertexPositionColor[(360 + 1) * 3];
double radObliq = obliquity * Math.PI / (180 * 60 * 60);
double cosObliq = Math.Cos(radObliq);
double sinObliq = Math.Sin(radObliq);
for (int t = 0; t <= 360; t++)
{
float rad = MathHelper.ToRadians(t);
float x = (float)(Math.Cos(rad) * au);
float r = (float)(Math.Sin(rad) * au);
float y = (float)cosObliq * r;
float z = (float)sinObliq * r;
vertices[0 + t] = new VertexPositionColor(
new Vector3(x, r, 0), Color.Red); // 黄道傾斜角=0(天の赤道面)
vertices[361 + t] = new VertexPositionColor(
new Vector3(x, y, z), Color.Yellow); // 黄道
vertices[722 + t] = new VertexPositionColor(
new Vector3(x, y, 0), Color.Cyan); // 黄道を天の赤道面に投影
}
vertexBuffer = new VertexBuffer(GraphicsDevice,
typeof(VertexPositionColor), vertices.Length, BufferUsage.WriteOnly);
vertexBuffer.SetData(vertices);
// 黄道傾斜角が南中時間に与える影響
int solarYearSec = (int)(solarYear * 24 * 60 * 60); // 太陽年(s)
int[] culmination = new int[365 + 1]; // 南中(正中)
int day = 0;
for (int t = 0; t < solarYearSec; t++)
{
// 地球を基準とした太陽の公転
double rad = (2 * Math.PI) * t / solarYearSec;
double x = Math.Cos(rad) * au;
double r = Math.Sin(rad) * au;
double y = cosObliq * r;
//double z = sinObliq * r;
double radCelestialEquator = Math.Atan2(y, x); // 天の赤道上の角度
if (radCelestialEquator < 0) radCelestialEquator += (2 * Math.PI);
// 地球の自転
double radEarthRotation = (2 * Math.PI) * ((t / siderealDay) % 1.0);
if (radCelestialEquator <= radEarthRotation)
{
culmination[day++] = t;
t += 86164; // 1回転する間は追い越さないので飛ばす
}
}
for (int i = 0; i < culmination.Length; i++)
{
Console.WriteLine(string.Format("{0} {1}", i, new TimeSpan(0, 0, culmination[i])));
}
base.LoadContent();
}
protected override void Update(GameTime gameTime)
{
KeyboardState kState = Keyboard.GetState();
if (kState.IsKeyDown(Keys.Escape)) Exit();
if (kState.IsKeyDown(Keys.Up)) camLat = Math.Min(camLat + 1, 89.9f);
if (kState.IsKeyDown(Keys.Down)) camLat = Math.Max(camLat - 1, -89.9f);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
GraphicsDevice.BlendState = BlendState.AlphaBlend;
// カメラ
float rad = MathHelper.ToRadians(camLat);
float x = (float)Math.Cos(rad) * camDist;
float z = (float)Math.Sin(rad) * camDist;
effect.View = Matrix.CreateLookAt(
new Vector3(x, 0, z), Vector3.Zero, Vector3.UnitZ);
GraphicsDevice.SetVertexBuffer(vertexBuffer);
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
GraphicsDevice.DrawPrimitives(PrimitiveType.LineStrip, 0, 360);
GraphicsDevice.DrawPrimitives(PrimitiveType.LineStrip, 361, 360);
GraphicsDevice.DrawPrimitives(PrimitiveType.LineStrip, 722, 360);
}
sprite.Begin();
string text = string.Format("lat={0:f0}", camLat);
sprite.DrawString(font, text, new Vector2(0, 0), Color.White);
sprite.End();
base.Draw(gameTime);
}
}
}
最終更新:2012年12月31日 15:43