カウンタ

  マウスからの入力

Google
▲探し物はこちら

 せっかくキーボードの入力が出来るようになったので、今度はマウスでカメラを操作したいと思います。マウスの左ボタンを押しながら上下左右に移動させるとカメラが回転します。

マウスからの入力

 下のリンクから今回のプロジェクトをダウンロードできます。

ファイル名 言語 サイズ バージョン
inputmouse_cs_1_1.zip C# 24KB 1.1
inputmouse_vb_1_1.zip VB.NET 30KB 1.1
inputmouse_cpp_1_1.zip C++/CLI 14KB 1.1

 今回のメインコードファイルを載せます。重要なコードを赤色で表示させています

MainSample.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace MDXSample
{
    /// <summary>
    /// メインサンプルクラス
    /// </summary>
    public partial class MainSample : IDisposable
    {
        /// <summary>
        /// カメラレンズの位置(θ)
        /// </summary>
        private float _lensPosTheta = 270.0f;

        /// <summary>
        /// カメラレンズの位置(φ)
        /// </summary>
        private float _lensPosPhi = 0.0f;

        /// <summary>
        /// 1つ前のマウスの位置
        /// </summary>
        private Point _oldMousePoint = Point.Empty;


        /// <summary>
        /// アプリケーションの初期化
        /// </summary>
        /// <param name="topLevelForm">トップレベルウインドウ</param>
        /// <returns>全ての初期化がOKなら true, ひとつでも失敗したら false を返すようにする</returns>
        /// <remarks>
        /// false を返した場合は、自動的にアプリケーションが終了するようになっている
        /// </remarks>
        public bool InitializeApplication(MainForm topLevelForm)
        {
            // フォームの参照を保持
            this._form = topLevelForm;

            // 入力イベント作成
            this.CreateInputEvent(topLevelForm);

            // マウス移動イベント
            topLevelForm.MouseMove += new MouseEventHandler(this.form_MouseMove);

            try
            {
                // Direct3D デバイス作成
                this.CreateDevice(topLevelForm);

                // フォントの作成
                this.CreateFont();
            }
            catch (DirectXException ex)
            {
                // 例外発生
                MessageBox.Show(ex.ToString(), "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            // 四角形ポリゴン作成
            this.CreateSquarePolygon();
            
            // 射影変換を設定
            this._device.Transform.Projection = Matrix.PerspectiveFovLH(
                Geometry.DegreeToRadian(60.0f),
                (float)this._device.Viewport.Width / (float)this._device.Viewport.Height,
                1.0f, 100.0f);

            // ライトを無効
            this._device.RenderState.Lighting = false;

            // カリングを無効にしてポリゴンの裏も描画する
            //this._device.RenderState.CullMode = Cull.None;

            return true;
        }

        /// <summary>
        /// マウス移動イベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void form_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                // 回転
                this._lensPosTheta -= e.Location.X - this._oldMousePoint.X;
                this._lensPosPhi += e.Location.Y - this._oldMousePoint.Y;

                // φに関しては制限をつける
                if (this._lensPosPhi >= 90.0f)
                {
                    this._lensPosPhi = 89.9999f;
                }
                else if (this._lensPosPhi <= -90.0f)
                {
                    this._lensPosPhi = -89.9999f;
                }
            }
            // マウスの位置を記憶
            this._oldMousePoint = e.Location;
        }

        /// <summary>
        /// メインループ処理
        /// </summary>
        public void MainLoop()
        {
            // レンズの位置を三次元極座標で変換
            float radius = 10.0f;
            float theta = Geometry.DegreeToRadian(this._lensPosTheta);
            float phi = Geometry.DegreeToRadian(this._lensPosPhi);
            Vector3 lensPosition = new Vector3(
                (float)(radius * Math.Cos(theta) * Math.Cos(phi)),
                (float)(radius * Math.Sin(phi)),
                (float)(radius * Math.Sin(theta) * Math.Cos(phi)));

            // ビュー変換行列を左手座標系ビュー行列で設定する
            this._device.Transform.View = Matrix.LookAtLH(
                lensPosition, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));


            // 描画内容を単色でクリアし、Zバッファもクリア
            this._device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.DarkBlue, 1.0f, 0);

            // 「BeginScene」と「EndScene」の間に描画内容を記述する
            this._device.BeginScene();


            // 四角形ポリゴン描画
            this.RenderSquarePolygon();

            // 文字列の描画
            this._font.DrawText(null, "マウスによるカメラの回転", 0, 0, Color.White);
            this._font.DrawText(null, "θ:" + this._lensPosTheta, 0, 12, Color.White);
            this._font.DrawText(null, "φ:" + this._lensPosPhi, 0, 24, Color.White);
            this._font.DrawText(null, "マウス位置:" + this._oldMousePoint, 0, 36, Color.White);


            // 描画はここまで
            this._device.EndScene();

            // 実際のディスプレイに描画
            this._device.Present();
        }

        /// <summary>
        /// リソースの破棄をするために呼ばれる
        /// </summary>
        public void Dispose()
        {
            // 頂点バッファを解放
            if (this._vertexBuffer != null)
            {
                this._vertexBuffer.Dispose();
            }

            // フォントのリソースを解放
            if (this._font != null)
            {
                this._font.Dispose();
            }

            // Direct3D デバイスのリソース解放
            if (this._device != null)
            {
                this._device.Dispose();
            }
        }
    }
}

 では、赤文字の部分を説明していきます。MainSamplePartial.cs ファイルのコードはこちらです。


/// <summary>
/// 1つ前のマウスの位置
/// </summary>
private Point _oldMousePoint = Point.Empty;

 マウスの移動量を調べるために、常にマウスの位置を記憶しておく必要があるので宣言しておきます。


// マウス移動イベント
topLevelForm.MouseMove += new MouseEventHandler(this.form_MouseMove);

 キーボードの時と同じようにフォームのイベントとしてマウスの移動イベントを受け取れるようにします。マウスのイベントは他にもマウスのボタンを押したときや放したときがありますが、今回は移動だけで済んでしまうので1つだけです。


/// <summary>
/// マウス移動イベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void form_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        // 回転
        this._lensPosTheta -= e.Location.X - this._oldMousePoint.X;
        this._lensPosPhi += e.Location.Y - this._oldMousePoint.Y;

        // φに関しては制限をつける
        if (this._lensPosPhi >= 90.0f)
        {
            this._lensPosPhi = 89.9999f;
        }
        else if (this._lensPosPhi <= -90.0f)
        {
            this._lensPosPhi = -89.9999f;
        }
    }
    // マウスの位置を記憶
    this._oldMousePoint = e.Location;
}

 マウスが移動するたびにこのメソッドが呼ばれます。

 マウスの左ボタンを押しているかは「MouseEventArgs.Button」の状態がを調べることで分かります。「MouseButtons.Left」と同じならマウスの左ボタンが押されていることになります。

 後は、前回のマウスの位置と現在のマウスの位置(MouseEventArgs.Location)の差分で回転量を決めます。φは以前と同じように制限を付けます。

 最後に差分を比較できるようにマウスの位置を記憶しておきます。

その他の関連情報です▼