「VCS/XnaSphere2」の編集履歴(バックアップ)一覧はこちら

VCS/XnaSphere2 - (2012/12/13 (木) 13:33:20) の1つ前との変更点

追加された行は緑色になります。

削除された行は赤色になります。

|開発環境|Microsoft Visual C# 2010 Express (SP1)| |実行環境|Microsoft Windows XP Home Edition (SP3)| |プロジェクトの種類|Windows Game (4.0)| |プロジェクト名|XnaSphere2| VertexPositionNormalColor.cs #highlight(c#){{ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace XnaSphere { struct VertexPositionNormalColor : IVertexType { public Vector3 Position; public Vector3 Normal; public Color Color; public VertexPositionNormalColor(Vector3 position, Vector3 normal, Color color) { Position = position; Normal = normal; Color = color; } static readonly VertexDeclaration VertexDeclaration = new VertexDeclaration( new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0), new VertexElement(sizeof(float) * 3, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0), new VertexElement(sizeof(float) * 6, VertexElementFormat.Color, VertexElementUsage.Color, 0)); VertexDeclaration IVertexType.VertexDeclaration { get { return VertexDeclaration; } } } } }} Game1.cs #highlight(c#){{ // 球面線形補間 using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; namespace XnaSphere { class Game1 : Game { GraphicsDeviceManager graphics; SpriteBatch sprite; SpriteFont font; BasicEffect effect; VertexBuffer vertexBuffer; IndexBuffer indexBuffer; // fps int sec; int draw = 0; int fps = 0; // カメラ int camLat = 0; int camLong = 90; float camDist = 5; public Game1() { graphics = new GraphicsDeviceManager(this); graphics.PreferredBackBufferWidth = 1280; graphics.PreferredBackBufferHeight = 720; Content.RootDirectory = "Content"; IsMouseVisible = true; } protected override void LoadContent() { font = Content.Load<SpriteFont>("SpriteFont1"); sprite = new SpriteBatch(GraphicsDevice); effect = new BasicEffect(GraphicsDevice); //effect.VertexColorEnabled = true; effect.EnableDefaultLighting(); effect.Projection = Matrix.CreatePerspectiveFieldOfView( MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 1, 100); // 頂点バッファ int stackNum = 16; // 輪切りの数 int[] dir = { 0, 1, 0, -1, 0, 1 }; // 方向配列 VertexPositionNormalColor[] vertices = new VertexPositionNormalColor[stackNum * stackNum + 2]; int i = 0; vertices[i++] = new VertexPositionNormalColor( new Vector3(0, 1, 0), new Vector3(0, 1, 0), Color.Yellow); for (int stack = 1; stack < stackNum; stack++) { float rad = ((stackNum - 2 * stack) / (float)stackNum) * MathHelper.PiOver2; float y = (float)Math.Sin(rad); float r = (float)Math.Cos(rad); int sliceNum = Math.Min(stack, stackNum - stack); // 1象限内の頂点数 for (int quad = 0; quad < 4; quad++) // 4象限 { // クォータニオン(四元数)は原点からのベクトルと原点を中心とした角度(時計回り?) // を持つ。開始点と終了点ともにベクトルで表せるので角度は0である。 Quaternion qs = new Quaternion(dir[quad + 1] * r, y, dir[quad + 0] * r, 0); Quaternion qe = new Quaternion(dir[quad + 2] * r, y, dir[quad + 1] * r, 0); for (int slice = 0; slice < sliceNum; slice++) { // 球面線形補間 Quaternion q = Quaternion.Slerp(qs, qe, slice / (float)sliceNum); q.Normalize(); Vector3 normal = new Vector3(q.X, q.Y, q.Z); vertices[i++] = new VertexPositionNormalColor( normal, normal, (i & 1) == 0 ? Color.Red : Color.Yellow); } } } vertices[i++] = new VertexPositionNormalColor( new Vector3(0, -1, 0), new Vector3(0, -1, 0), Color.Yellow); vertexBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionNormalColor), vertices.Length, BufferUsage.WriteOnly); vertexBuffer.SetData(vertices); // 索引バッファ short[] indices = new short[stackNum * stackNum * 6]; i = 0; int prevHead = 0; // 前の先頭頂点番号 int prevVtx = 1; // 前の頂点数 for (int stack = 0; stack < stackNum / 2; stack++) { int currHead = prevHead + prevVtx; // 現在の先頭頂点番号 int currVtx = 4 * (stack + 1); // 現在の頂点数 for (int quad = 0; quad < 4; quad++) // 4象限 { int prevQuad = quad * stack; // 前の象限オフセット int currQuad = quad * (stack + 1); // 現在の象限オフセット for (int n = 0; ; n++) { indices[i++] = (short)(prevHead + (prevQuad + n) % prevVtx); indices[i++] = (short)(currHead + (currQuad + n)); indices[i++] = (short)(currHead + (currQuad + n + 1) % currVtx); if (stack <= n) break; indices[i++] = (short)(prevHead + (prevQuad + n)); indices[i++] = (short)(currHead + (currQuad + n + 1)); indices[i++] = (short)(prevHead + (prevQuad + n + 1) % prevVtx); } } prevHead = currHead; prevVtx = currVtx; } for (int stack = stackNum / 2 - 1; 0 <= stack; stack--) { int currHead = prevHead + prevVtx; int currVtx = Math.Max(4 * stack, 1); for (int quad = 0; quad < 4; quad++) // 4象限 { int prevQuad = quad * (stack + 1); int currQuad = quad * stack; for (int n = 0; ; n++) { indices[i++] = (short)(currHead + (currQuad + n) % currVtx); indices[i++] = (short)(prevHead + (prevQuad + n + 1) % prevVtx); indices[i++] = (short)(prevHead + (prevQuad + n)); if (stack <= n) break; indices[i++] = (short)(currHead + (currQuad + n)); indices[i++] = (short)(currHead + (currQuad + n + 1) % currVtx); indices[i++] = (short)(prevHead + (prevQuad + n + 1)); } } prevHead = currHead; prevVtx = currVtx; } indexBuffer = new IndexBuffer(GraphicsDevice, typeof(short), indices.Length, BufferUsage.WriteOnly); indexBuffer.SetData(indices); base.LoadContent(); } protected override void Update(GameTime gameTime) { KeyboardState kState = Keyboard.GetState(); if (kState.IsKeyDown(Keys.Escape)) Exit(); if (kState.IsKeyDown(Keys.Up)) camLat++; if (kState.IsKeyDown(Keys.Down)) camLat--; if (kState.IsKeyDown(Keys.Left)) camLong = (camLong + 1) % 360; if (kState.IsKeyDown(Keys.Right)) camLong = (camLong + 359) % 360; if (kState.IsKeyDown(Keys.PageUp)) camDist -= 0.1f; if (kState.IsKeyDown(Keys.PageDown)) camDist += 0.1f; base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); //GraphicsDevice.RasterizerState = // new RasterizerState { FillMode = FillMode.WireFrame }; // カメラ位置 float rad = MathHelper.ToRadians(camLat); float y = (float)Math.Sin(rad) * camDist; float r = (float)Math.Cos(rad) * camDist; rad = MathHelper.ToRadians(camLong); float x = (float)Math.Cos(rad) * r; float z = (float)Math.Sin(rad) * r; effect.View = Matrix.CreateLookAt(new Vector3(x, y, z), Vector3.Zero, Vector3.Up); GraphicsDevice.SetVertexBuffer(vertexBuffer); GraphicsDevice.Indices = indexBuffer; foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertexBuffer.VertexCount, 0, indexBuffer.IndexCount / 3); } // fps draw++; if (gameTime.TotalGameTime.Seconds != sec) { fps = draw; draw = 0; sec = gameTime.TotalGameTime.Seconds; } sprite.Begin(); string text = String.Format( "fps={0} lat={1} long={2} dist={3:f1}", fps, camLat, camLong, camDist); sprite.DrawString(font, text, new Vector2(0, 0), Color.White); sprite.End(); base.Draw(gameTime); } } } }}
|開発環境|Microsoft Visual C# 2010 Express (SP1)| |実行環境|Microsoft Windows XP Home Edition (SP3)| |プロジェクトの種類|Windows Game (4.0)| |プロジェクト名|XnaSphere2| CustomVertex.cs #highlight(c#){{ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace CustomVertex { struct VertexPositionNormalColor : IVertexType { public Vector3 Position; public Vector3 Normal; public Color Color; public VertexPositionNormalColor(Vector3 position, Vector3 normal, Color color) { Position = position; Normal = normal; Color = color; } static readonly VertexDeclaration VertexDeclaration = new VertexDeclaration( new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0), new VertexElement(sizeof(float) * 3, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0), new VertexElement(sizeof(float) * 6, VertexElementFormat.Color, VertexElementUsage.Color, 0)); VertexDeclaration IVertexType.VertexDeclaration { get { return VertexDeclaration; } } } } }} Game1.cs #highlight(c#){{ // XnaSphere2 - XNA 球体(法線) using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using CustomVertex; namespace XnaSphere { class Game1 : Game { GraphicsDeviceManager graphics; SpriteBatch sprite; SpriteFont font; BasicEffect effect; VertexBuffer vertexBuffer; IndexBuffer indexBuffer; // fps int sec; int draw = 0; int fps = 0; // カメラ int camLat = 0; int camLong = 90; float camDist = 5; public Game1() { graphics = new GraphicsDeviceManager(this); graphics.PreferredBackBufferWidth = 1280; graphics.PreferredBackBufferHeight = 720; Content.RootDirectory = "Content"; IsMouseVisible = true; } protected override void LoadContent() { font = Content.Load<SpriteFont>("SpriteFont1"); sprite = new SpriteBatch(GraphicsDevice); effect = new BasicEffect(GraphicsDevice); //effect.VertexColorEnabled = true; effect.EnableDefaultLighting(); effect.Projection = Matrix.CreatePerspectiveFieldOfView( MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 1, 100); // 頂点バッファ int stackNum = 16; // 輪切りの数 VertexPositionNormalColor[] vertices = new VertexPositionNormalColor[stackNum * stackNum + 2]; int i = 0; vertices[i++] = new VertexPositionNormalColor( new Vector3(0, 1, 0), new Vector3(0, 1, 0), Color.Yellow); for (int stack = 1; stack < stackNum; stack++) { float rad = ((stackNum - 2 * stack) / (float)stackNum) * MathHelper.PiOver2; float y = (float)Math.Sin(rad); float r = (float)Math.Cos(rad); int sliceNum = 4 * Math.Min(stack, stackNum - stack); // 放射頂点の数 for (int slice = 0; slice < sliceNum; slice++) { rad = (slice / (float)sliceNum) * MathHelper.TwoPi; float x = (float)Math.Cos(rad) * r; float z = (float)Math.Sin(rad) * r; Vector3 normal = Vector3.Normalize(new Vector3(x, y, z)); vertices[i++] = new VertexPositionNormalColor( normal, normal, (slice & 1) == 0 ? Color.Red : Color.Yellow); } } vertices[i++] = new VertexPositionNormalColor( new Vector3(0, -1, 0), new Vector3(0, -1, 0), Color.Yellow); vertexBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionNormalColor), vertices.Length, BufferUsage.WriteOnly); vertexBuffer.SetData(vertices); // 索引バッファ short[] indices = new short[stackNum * stackNum * 6]; i = 0; int prevHead = 0; // 前の先頭頂点番号 int prevVtx = 1; // 前の頂点数 for (int stack = 0; stack < stackNum / 2; stack++) { int currHead = prevHead + prevVtx; // 現在の先頭頂点番号 int currVtx = 4 * (stack + 1); // 現在の頂点数 for (int quad = 0; quad < 4; quad++) // 4象限 { int prevQuad = quad * stack; // 前の象限オフセット int currQuad = quad * (stack + 1); // 現在の象限オフセット for (int n = 0; ; n++) { indices[i++] = (short)(prevHead + (prevQuad + n) % prevVtx); indices[i++] = (short)(currHead + (currQuad + n)); indices[i++] = (short)(currHead + (currQuad + n + 1) % currVtx); if (stack <= n) break; indices[i++] = (short)(prevHead + (prevQuad + n)); indices[i++] = (short)(currHead + (currQuad + n + 1)); indices[i++] = (short)(prevHead + (prevQuad + n + 1) % prevVtx); } } prevHead = currHead; prevVtx = currVtx; } for (int stack = stackNum / 2 - 1; 0 <= stack; stack--) { int currHead = prevHead + prevVtx; int currVtx = Math.Max(4 * stack, 1); for (int quad = 0; quad < 4; quad++) // 4象限 { int prevQuad = quad * (stack + 1); int currQuad = quad * stack; for (int n = 0; ; n++) { indices[i++] = (short)(currHead + (currQuad + n) % currVtx); indices[i++] = (short)(prevHead + (prevQuad + n + 1) % prevVtx); indices[i++] = (short)(prevHead + (prevQuad + n)); if (stack <= n) break; indices[i++] = (short)(currHead + (currQuad + n)); indices[i++] = (short)(currHead + (currQuad + n + 1) % currVtx); indices[i++] = (short)(prevHead + (prevQuad + n + 1)); } } prevHead = currHead; prevVtx = currVtx; } indexBuffer = new IndexBuffer(GraphicsDevice, typeof(short), indices.Length, BufferUsage.WriteOnly); indexBuffer.SetData(indices); base.LoadContent(); } protected override void Update(GameTime gameTime) { KeyboardState kState = Keyboard.GetState(); if (kState.IsKeyDown(Keys.Escape)) Exit(); if (kState.IsKeyDown(Keys.Up)) camLat++; if (kState.IsKeyDown(Keys.Down)) camLat--; if (kState.IsKeyDown(Keys.Left)) camLong = (camLong + 1) % 360; if (kState.IsKeyDown(Keys.Right)) camLong = (camLong + 359) % 360; if (kState.IsKeyDown(Keys.PageUp)) camDist -= 0.1f; if (kState.IsKeyDown(Keys.PageDown)) camDist += 0.1f; base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); //GraphicsDevice.RasterizerState = // new RasterizerState { FillMode = FillMode.WireFrame }; // カメラ位置 float rad = MathHelper.ToRadians(camLat); float y = (float)Math.Sin(rad) * camDist; float r = (float)Math.Cos(rad) * camDist; rad = MathHelper.ToRadians(camLong); float x = (float)Math.Cos(rad) * r; float z = (float)Math.Sin(rad) * r; effect.View = Matrix.CreateLookAt(new Vector3(x, y, z), Vector3.Zero, Vector3.Up); GraphicsDevice.SetVertexBuffer(vertexBuffer); GraphicsDevice.Indices = indexBuffer; foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertexBuffer.VertexCount, 0, indexBuffer.IndexCount / 3); } // fps draw++; if (gameTime.TotalGameTime.Seconds != sec) { fps = draw; draw = 0; sec = gameTime.TotalGameTime.Seconds; } sprite.Begin(); string text = String.Format( "fps={0} lat={1} long={2} dist={3:f1}", fps, camLat, camLong, camDist); sprite.DrawString(font, text, new Vector2(0, 0), Color.White); sprite.End(); base.Draw(gameTime); } } } }}

表示オプション

横に並べて表示:
変化行の前後のみ表示: