開発環境 Microsoft Visual C# 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 Windows Game (4.0)
プロジェクト名 XnaHwiModel

CustomVertex.cs
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
 
namespace CustomVertex
{
    struct VertexPosition : IVertexType
    {
        public Vector3 Position;
 
        public VertexPosition(Vector3 position)
        {
            Position = position;
        }
 
        static readonly VertexDeclaration VertexDeclaration = new VertexDeclaration(
            new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0)
        );
 
        VertexDeclaration IVertexType.VertexDeclaration { get { return VertexDeclaration; } }
    }
}
 

Game1.cs
/*
 * プロジェクト/プロパティ
 * [XNA Game Studio]タブ
 * Use HiDef to access the complete API
 */
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using CustomVertex;
 
namespace XnaHwiModel
{
    class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch sprite;
        SpriteFont font;
        Model model;
        Effect effect;
        VertexBuffer instanceDataStream;
 
        // fps
        int sec;
        int draw = 0;
        int fps = 0;
 
        // カメラ
        Vector3 camPos = new Vector3(-10, 0, -10);
        float camLat = 30;
        float camLon = 45;
 
        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");
            //model = Content.Load<Model>("aircraft");
            model = Content.Load<Model>("dice6");
 
            effect = Content.Load<Effect>("Effect1");
            effect.Parameters["World"].SetValue(Matrix.Identity);
            effect.Parameters["Projection"].SetValue(Matrix.CreatePerspectiveFieldOfView(
                MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 0.1f, 1000));
 
            int n = 20;
            VertexPosition[] vp = new VertexPosition[n * n * n];
            int i = 0;
            for (int y = 0; y < n; y++)
            {
                for (int x = 0; x < n; x++)
                {
                    for (int z = 0; z < n; z++)
                    {
                        vp[i++] = new VertexPosition(new Vector3(x * 15, y * 5, z * 15));
                    }
                }
            }
 
            instanceDataStream = new VertexBuffer(GraphicsDevice,
                typeof(VertexPosition), vp.Length, BufferUsage.WriteOnly);
            instanceDataStream.SetData(vp);
 
            base.LoadContent();
        }
 
        protected override void Update(GameTime gameTime)
        {
            KeyboardState kState = Keyboard.GetState();
            if (kState.IsKeyDown(Keys.Escape)) Exit();
            if (kState.IsKeyDown(Keys.W)) Move(0, 0);
            if (kState.IsKeyDown(Keys.S)) Move(180, 0);
            if (kState.IsKeyDown(Keys.A)) Move(0, -90);
            if (kState.IsKeyDown(Keys.D)) Move(0, 90);
            if (kState.IsKeyDown(Keys.Up)) camLat = Math.Min(camLat + 1, 89);
            if (kState.IsKeyDown(Keys.Down)) camLat = Math.Max(camLat - 1, -89);
            if (kState.IsKeyDown(Keys.Left)) camLon = (camLon + 359) % 360;
            if (kState.IsKeyDown(Keys.Right)) camLon = (camLon + 1) % 360;
            if (kState.IsKeyDown(Keys.PageUp)) Move(90, 0);
            if (kState.IsKeyDown(Keys.PageDown)) Move(-90, 0);
 
            base.Update(gameTime);
        }
 
        private void Move(int lat, int lon)
        {
            float rad = MathHelper.ToRadians(camLat + lat);
            float y = (float)Math.Sin(rad) * 0.2f;
            float r = (float)Math.Cos(rad) * 0.2f;
            if (lon == 0) camPos.Y += y;
            rad = MathHelper.ToRadians(camLon + lon);
            camPos.X += (float)Math.Cos(rad) * r;
            camPos.Z += (float)Math.Sin(rad) * r;
        }
 
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.BlendState = BlendState.AlphaBlend;
            //GraphicsDevice.RasterizerState = new RasterizerState { FillMode = FillMode.WireFrame};
 
            // カメラ位置
            float rad = MathHelper.ToRadians(camLat);
            float y = (float)Math.Sin(rad);
            float r = (float)Math.Cos(rad);
            rad = MathHelper.ToRadians(camLon);
            float x = (float)Math.Cos(rad) * r;
            float z = (float)Math.Sin(rad) * r;
            Matrix view = Matrix.CreateLookAt(camPos, camPos + new Vector3(x, y, z), Vector3.Up);
            effect.Parameters["View"].SetValue(view);
 
            foreach (ModelMesh mesh in model.Meshes)
            {
                MeshDraw(mesh);
            }
 
            // fps
            draw++;
            if (gameTime.TotalGameTime.Seconds != sec)
            {
                fps = draw;
                draw = 0;
                sec = gameTime.TotalGameTime.Seconds;
            }
 
            // 2D描画
            sprite.Begin();
            string text = String.Format("fps={0} lat={1:f0} long={2:f0}", fps, camLat, camLon);
            sprite.DrawString(font, text, new Vector2(0, 0), Color.White);
            text = String.Format("x={0:f0} y={1:f0} z={2:f0}", camPos.X, camPos.Y, camPos.Z);
            sprite.DrawString(font, text, new Vector2(0, 20), Color.White);
            sprite.End();
 
            base.Draw(gameTime);
        }
 
        private void MeshDraw(ModelMesh mesh)
        {
            foreach (ModelMeshPart mpart in mesh.MeshParts)
            {
                VertexBufferBinding[] bindings;
                bindings = new VertexBufferBinding[2];
                bindings[0] = new VertexBufferBinding(mpart.VertexBuffer, 0);
                bindings[1] = new VertexBufferBinding(instanceDataStream, 0, 1);
                GraphicsDevice.SetVertexBuffers(bindings);
                GraphicsDevice.Indices = mpart.IndexBuffer;
 
                BasicEffect be = (BasicEffect)mpart.Effect;
                if (be.TextureEnabled)
                {
                    effect.CurrentTechnique = effect.Techniques["TechTexture"];
                    effect.Parameters["Texture"].SetValue(be.Texture);
                }
                else
                {
                    effect.CurrentTechnique = effect.Techniques["TechColor"];
                    effect.Parameters["Color"].SetValue(be.DiffuseColor);
                }
 
                foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                {
                    pass.Apply();
                    GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList,
                        mpart.VertexOffset, 0, mpart.NumVertices, mpart.StartIndex,
                        mpart.PrimitiveCount, instanceDataStream.VertexCount);
                }
            }
        }
    }
}
 

Effect1.fx
float4x4 World;
float4x4 View;
float4x4 Projection;
 
float3 Color : COLOR0;
texture Texture;
 
sampler TextureSampler = sampler_state
{
	texture = <Texture>;
	mipfilter = linear;
	minfilter = linear;
	magfilter = linear;
};
 
struct VS_Input
{
	float4 Position : POSITION0;
	float4 Color : COLOR0;
	float2 TexCoord : TEXCOORD0;
};
 
struct VS_ColorOutput
{
	float4 Position : POSITION0;
	float4 Color : COLOR0;
};
 
struct VS_TextureOutput
{
	float4 Position : POSITION0;
	float2 TexCoord : TEXCOORD0;
};
 
VS_ColorOutput VS_Color(VS_Input input, float3 transform : POSITION1)
{
	VS_ColorOutput output;
	float4 worldPosition = mul(input.Position + float4(transform, 0), World);
	float4 viewPosition = mul(worldPosition, View);
	output.Position = mul(viewPosition, Projection);
	output.Color = float4(Color, 1.0f);
	return output;
}
 
VS_TextureOutput VS_Texture(VS_Input input, float3 transform : POSITION1)
{
	VS_TextureOutput output;
	float4 worldPosition = mul(input.Position + float4(transform, 0), World);
	float4 viewPosition = mul(worldPosition, View);
	output.Position = mul(viewPosition, Projection);
	output.TexCoord = input.TexCoord;
	return output;
}
 
float4 PS_Color(float4 color : COLOR0) : COLOR0
{
	return color;
}
 
float4 PS_Texture(float2 texCoord : TEXCOORD0) : COLOR0
{
	return tex2D(TextureSampler, texCoord);
}
 
technique TechColor
{
	pass Pass1
	{
		VertexShader = compile vs_3_0 VS_Color();
		PixelShader = compile ps_3_0 PS_Color();
	}
}
 
technique TechTexture
{
	pass Pass1
	{
		VertexShader = compile vs_3_0 VS_Texture();
		PixelShader = compile ps_3_0 PS_Texture();
	}
}
 
最終更新:2012年12月28日 20:49