Load the X file and view the model

Page update date :
Page creation date :

summary

The model data is read from the X file (.x) and displayed.

Xファイルを読み込んでモデルを表示

Operating environment

Prerequisites

Supported XNA Versions
  • 2.0
  • 3.0
  • 3.1
  • 4.0
Supported Platforms
  • Windows (XP SP2, Vista. 7)
  • Xbox360
  • Windows Phone 7
Windows Required Vertex Shader Version 2.0
Windows Required Pixel Shader Version 2.0

Operating environment

platform
  • Windows 7
  • Xbox360
  • Windows Phone 7 Emulator

substance

What is an X file

An X file is a file that can be used as model data by combining vertex data with location information and normal information, texture reference paths, frames, anime data, etc. into one. There are many other files that contain model data, but X files were used as standard model data until DirectX9 and are supported as a standard format by XNA.

X files save you the trouble of building vertex data directly in the program and make it possible to draw the geometry of complex models with very simplified code writing. Since the data itself is described in an X file, the advantage is that the program does not need to be changed even if the shape changes.

Model data files such as X files are mainly created with "modeling software" and output files. I mainly use modeling software called "Metasequoia", and there is a shareware version and a freeware version, but I recommend the freeware version because it can output X files. It is one of the few Japanese software that can output X files with freeware.

In this case, I created a simple model like the one below and output it as an X file.

メタセコイアでモデルを作成

When output, the file will look like the one below. In this case, we will use the name "Model.x".

出力したXファイル

Register X files to content

Add the X file you created to the Content folder of your project. For details on how to add resources, see "Loading resources (contents)".

Xファイルをコンテンツに追加

field

To read data from an X file and display it, use the "Model" class. The Model class contains all the "vertex buffers", "index buffers", "effects", "textures", etc. necessary for displaying the model, so you only need to prepare this one.

/// <summary>
/// モデル
/// </summary>
private Model model = null;

Loading Models

The model data is loaded from the "ContentManager" in the "Game.LoadContent" method. It's the same as loading textures, fonts, etc. The asset name is registered as "Model".

// モデルを作成
this.model = this.Content.Load<Model>("Model");

Setting Parameters

This time, the parameters do not change all the time, so they are set immediately after loading the model data. If the model is constantly changing positions or camera settings, I think it will be set in the Game.Draw method.

// 今回はパラメータをあらかじめ設定しておく
foreach (ModelMesh mesh in this.model.Meshes)
{
    foreach (BasicEffect effect in mesh.Effects)
    {
        // デフォルトのライト適用
        effect.EnableDefaultLighting();

        // ビューマトリックスをあらかじめ設定 ((9, 9, 9) から原点を見る)
        effect.View = Matrix.CreateLookAt(
            new Vector3(9.0f, 9.0f, 9.0f),
            Vector3.Zero,
            Vector3.Up
        );

        // プロジェクションマトリックスをあらかじめ設定
        effect.Projection = Matrix.CreatePerspectiveFieldOfView(
            MathHelper.ToRadians(45.0f),
            (float)this.GraphicsDevice.Viewport.Width /
                (float)this.GraphicsDevice.Viewport.Height,
            1.0f,
            100.0f
        );
    }
}

Since a single "Model" may contain multiple meshes, it is enumerated in "Model.Meshes" and set to all meshes.

Also, since one "ModelMesh" may contain multiple effects, I list them in "ModelMesh.Effects" and set them to all effects.

Here we have pre-set the default light settings, the view matrix and the projection matrix.

drawing

Drawing a model is very simple, and you can draw it with a single "ModelMesh.Draw" method. Since we are drawing in mesh units, we use "Model.Meshes" to enumerate and draw all meshes.

// モデルを描画
foreach (ModelMesh mesh in this.model.Meshes)
{
    mesh.Draw();
}

ModelMesh.Draw method

Draw each ModelMeshPart using the preset effects.

All Codes

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
#if WINDOWS_PHONE
using Microsoft.Xna.Framework.Input.Touch;
#endif

namespace XFile
{
    /// <summary>
    /// ゲームメインクラス
    /// </summary>
    public class GameMain : Microsoft.Xna.Framework.Game
    {
        /// <summary>
        /// グラフィックデバイス管理クラス
        /// </summary>
        private GraphicsDeviceManager graphics = null;

        /// <summary>
        /// スプライトのバッチ化クラス
        /// </summary>
        private SpriteBatch spriteBatch = null;

        /// <summary>
        /// モデル
        /// </summary>
        private Model model = null;


        /// <summary>
        /// GameMain コンストラクタ
        /// </summary>
        public GameMain()
        {
            // グラフィックデバイス管理クラスの作成
            this.graphics = new GraphicsDeviceManager(this);

            // ゲームコンテンツのルートディレクトリを設定
            this.Content.RootDirectory = "Content";

#if WINDOWS_PHONE
            // Windows Phone のデフォルトのフレームレートは 30 FPS
            this.TargetElapsedTime = TimeSpan.FromTicks(333333);

            // バックバッファサイズの設定
            this.graphics.PreferredBackBufferWidth = 480;
            this.graphics.PreferredBackBufferHeight = 800;

            // フルスクリーン表示
            this.graphics.IsFullScreen = true;
#endif
        }

        /// <summary>
        /// ゲームが始まる前の初期化処理を行うメソッド
        /// グラフィック以外のデータの読み込み、コンポーネントの初期化を行う
        /// </summary>
        protected override void Initialize()
        {
            // TODO: ここに初期化ロジックを書いてください

            // コンポーネントの初期化などを行います
            base.Initialize();
        }

        /// <summary>
        /// ゲームが始まるときに一回だけ呼ばれ
        /// すべてのゲームコンテンツを読み込みます
        /// </summary>
        protected override void LoadContent()
        {
            // テクスチャーを描画するためのスプライトバッチクラスを作成します
            this.spriteBatch = new SpriteBatch(this.GraphicsDevice);

            // モデルを作成
            this.model = this.Content.Load<Model>("Model");

            // 今回はパラメータをあらかじめ設定しておく
            foreach (ModelMesh mesh in this.model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    // デフォルトのライト適用
                    effect.EnableDefaultLighting();

                    // ビューマトリックスをあらかじめ設定 ((9, 9, 9) から原点を見る)
                    effect.View = Matrix.CreateLookAt(
                        new Vector3(9.0f, 9.0f, 9.0f),
                        Vector3.Zero,
                        Vector3.Up
                    );

                    // プロジェクションマトリックスをあらかじめ設定
                    effect.Projection = Matrix.CreatePerspectiveFieldOfView(
                        MathHelper.ToRadians(45.0f),
                        (float)this.GraphicsDevice.Viewport.Width /
                            (float)this.GraphicsDevice.Viewport.Height,
                        1.0f,
                        100.0f
                    );
                }
            }
        }

        /// <summary>
        /// ゲームが終了するときに一回だけ呼ばれ
        /// すべてのゲームコンテンツをアンロードします
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: ContentManager で管理されていないコンテンツを
            //       ここでアンロードしてください
        }

        /// <summary>
        /// 描画以外のデータ更新等の処理を行うメソッド
        /// 主に入力処理、衝突判定などの物理計算、オーディオの再生など
        /// </summary>
        /// <param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
        protected override void Update(GameTime gameTime)
        {
            // Xbox 360 コントローラ、Windows Phone の BACK ボタンを押したときに
            // ゲームを終了させます
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            {
                this.Exit();
            }

            // TODO: ここに更新処理を記述してください

            // 登録された GameComponent を更新する
            base.Update(gameTime);
        }

        /// <summary>
        /// 描画処理を行うメソッド
        /// </summary>
        /// <param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
        protected override void Draw(GameTime gameTime)
        {
            // 画面を指定した色でクリアします
            this.GraphicsDevice.Clear(Color.CornflowerBlue);

            // モデルを描画
            foreach (ModelMesh mesh in this.model.Meshes)
            {
                mesh.Draw();
            }

            // 登録された DrawableGameComponent を描画する
            base.Draw(gameTime);
        }
    }
}