ビルボードのビルさん
■今回はビルボードに関して書こうと思います。
ビルボード用にモデルデータ(板ポリゴンのみ)を用意しました。
「borad.x」
xof 0302txt 0064 Mesh { 4; -1.00000;1.00000;0.00000;, 1.00000;1.00000;0.00000;, 1.00000;-1.00000;0.00000;, -1.00000;-1.00000;0.00000;; 1; 4;0,1,2,3;; MeshTextureCoords { 4; 0.00000;0.00000;, 1.00000;0.00000;, 1.00000;1.00000;, 0.00000;1.00000;; } MeshMaterialList { 1; 1; 0; Material { 1.000000;1.000000;1.000000;1.000000;; 0.000000; 0.000000;0.000000;0.000000;; 0.000000;0.000000;0.000000;; TextureFilename { "bill.jpg"; } } } }
今回はせっかくビルボードなので、テクスチャにビルさんが登場です。
■最初のソースはこんな感じて
namespace WindowsGame2_08 { public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; private double dAng = 0; private Model model; private Matrix mainView; private Matrix mainWorld; private Matrix mainProjection; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } protected override void Initialize() { model = Content.Load<Model>("borad"); mainProjection = Matrix.CreatePerspectiveFieldOfView( MathHelper.ToRadians(45.0f), (float)graphics.GraphicsDevice.Viewport.Width / (float)graphics.GraphicsDevice.Viewport.Height, 1.0f, 100.0f ); mainWorld = Matrix.CreateTranslation(0, 0, 0); base.Initialize(); } protected override void Update(GameTime gameTime) { // ビューマトリックス mainView = Matrix.CreateLookAt( new Vector3((float)(10.0 * Math.Sin(dAng)), 5.0f, (float)(10.0 * Math.Cos(dAng))), new Vector3(0, 0, 0), Vector3.Up ); dAng += 0.01; if (dAng > 3.141592 * 2) dAng -= 3.141592 * 2; //----------------------- base.Update(gameTime); } protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.CornflowerBlue); for (int j = -4; j < 5; j++) { for (int i = -4; i < 5; i++) { mainWorld = Matrix.CreateTranslation(i * 3.0f, 0.0f, j * 3.0f); foreach (ModelMesh mesh in model.Meshes) { foreach (BasicEffect effect in mesh.Effects) { effect.View = mainView; effect.World = mainWorld; effect.Projection = mainProjection; } mesh.Draw(); } } } base.Draw(gameTime); } } }
このプログラムを実行すると、ポリゴンは回転に合わせて、向きを変え、こっちをむいてくれません。
■こっちを向いてもらうために少し工夫が必要で、描画部分を修正します。
protected override void Draw(GameTime gameTime) { Matrix viewInvert = Matrix.Invert(mainView); viewInvert.M14 = 0.0f; viewInvert.M24 = 0.0f; viewInvert.M34 = 0.0f; viewInvert.M41 = 0.0f; viewInvert.M42 = 0.0f; viewInvert.M43 = 0.0f; viewInvert.M44 = 1.0f; graphics.GraphicsDevice.Clear(Color.CornflowerBlue); for (int j = -4; j < 5; j++) { for (int i = -4; i < 5; i++) { mainWorld = viewInvert * Matrix.CreateTranslation(i * 3.0f, 0.0f, j * 3.0f); foreach (ModelMesh mesh in model.Meshes) { foreach (BasicEffect effect in mesh.Effects) { effect.View = mainView; effect.World = mainWorld; effect.Projection = mainProjection; } mesh.Draw(); } } } base.Draw(gameTime); }
な感じで、Viewマトリックから逆ベクトルを求めて、モデルを必ず正面に向ける準備をします。
Matrix viewInvert = Matrix.Invert(mainView); viewInvert.M14 = 0.0f; viewInvert.M24 = 0.0f; viewInvert.M34 = 0.0f; viewInvert.M41 = 0.0f; viewInvert.M42 = 0.0f; viewInvert.M43 = 0.0f; viewInvert.M44 = 1.0f;
ここで生成したマトリックスをワールドマトリックスに掛け合わせておきます。
mainWorld = viewInvert * Matrix.CreateTranslation(i * 3.0f, 0.0f, j * 3.0f);