見出し画像

DirectX ボールを転がす1

これまでのところでグラフィックアセットを利用可能になりました。これからはDirectX Graphicsを活用して「ゴルフボールを転がす」プログラムを作成してみましょう。

DirectX TKは右手系

3Dグラフィックスのプログラミングでは、左手系(Left Handed System)と右手系(Right Handed System)の座標系を使用します。右手系の場合、下図のようにx軸とy軸の正の方向は左手系と同じですが、z軸の正方向が手前の方向になります。DirectX9の頃の3D座標系は左手系でしたが、DirectX11、12は右手系と左手系の両方が使用できます。DirectX TKはDirectX11、12に対応していますが、右手系です。

DirectX TKは右手系

ゴルフボールを転がすアプリの座標系を次に示します。

DirectX TKアプリの座標系


GolfBallクラスを宣言する

GolfBallクラスを宣言します。

#pragma once
#ifndef GOLF_BALL_DEFINED
#define GOLF_BALL_DEFINED

#include "StepTimer.h"

class GolfBall
{

};
#endif   // GOLF_BALL_DEFINED


メンバー定数とメンバー変数を宣言する

GolfBallクラスのメンバー定数と変数を宣言します。宣言するメンバー定数は公開し、メンバー変数は非公開にします。型、定数、変数を次に示します。

メンバー定数

  • 摩擦係数 static const float FRICTION

  • 最大移動速度 static const float MAX_SPEED

メンバー変数

  • DirectXグラフィックス Graphics* m_graphics

  • ゴルフボールモデル  Model* m_model

  • ゴルフボールの回転クォータニオン Quaternion m_quaternion

  • ゴルフボールの位置  Vector2 m_position

  • ゴルフボールの速度  Vector2 m_velocity

  • ゴルフボールの方向  Vector2 m_heading

  • ゴルフボールの質量  float m_mass

  • ゴルフボールの半径  float m_radius

これまでの宣言を追加したGolfBallクラスの宣言を次に示します。

#pragma once
#ifndef GOLF_BALL_DEFINED
#define GOLF_BALL_DEFINED

#include "StepTimer.h"

class GolfBall
{
public:
   // 摩擦係数
   static const float FRICTION;
   // 最大移動速度
   static const float MAX_SPEED;

private:
   // DirectXグラフィックス
   Graphics* m_graphics;

   // ゴルフボールモデル
   DirectX::Model* m_model;
   // ゴルフボールの回転を示すクォータニオン
   DirectX::SimpleMath::Quaternion m_quaternion;
   // ゴルフボールの位置
   DirectX::SimpleMath::Vector2 m_position;
   // ゴルフボールの速度
   DirectX::SimpleMath::Vector2 m_velocity;
   // ゴルフボールの方向
   DirectX::SimpleMath::Vector2 m_heading;
   // ゴルフボールの質量
   float m_mass;
   // ゴルフボールの半径
   float m_radius;
};
#endif   // GOLF_BALL_DEFINED


GolfBallクラスのアクセッサーを定義する

GolfBallクラス外部からメンバー変数にアクセスするためのアクセッサーをGolfBallクラスにインラインで定義し、公開します。

  • 位置を取得する Vector2 GetPosition() const

  • 位置を設定する void SetPosition(const Vector2& position)

  • 速度を取得する Vector2 GetVelocity() const

  • 速度を設定する void SetVelocity(const Vector2& velocity)

GolfBallクラスのメンバー関数を宣言する

GolfBallクラスのメンバー関数を宣言し、公開します。

  • コンストラクタ GolfBall(DirectX::Model* model)

  • デストラクタ ~GolfBall()

  • 初期化する Initialize()

  • 更新する void Update(const float& elapsedTime)

  • 描画する void Render()

  • 後処理を行う void Finalize()

  • ゴルフボールを転がす void Roll(const Vector2& direction, const float& force)

最終的なGolfBallクラス(GolfBall.h)の宣言を次に示します。

#pragma once
#ifndef GOLF_BALL_DEFINED
#define GOLF_BALL_DEFINED

#include "StepTimer.h"

class GolfBall
{
public:
   // 位置を取得する
   DirectX::SimpleMath::Vector2 GetPosition() const { return m_position; }
   // 位置を設定する
   void SetPosition(const DirectX::SimpleMath::Vector2& position) { m_position = position; }
   // 速度を取得する
   DirectX::SimpleMath::Vector2 GetVelocity() const { return m_velocity; }
   // 速度を設定する
   void SetVelocity(const DirectX::SimpleMath::Vector2& velocity) { m_velocity = velocity; }

public:
   // コンストラクタ
   GolfBall(DirectX::Model* model);
   // デストラクタ
   ~GolfBall();
   // 初期化する
   void Initialize();
   // 更新する
   void Update(const float& elapsedTime);
   // 描画する
   void Render();
   // 後処理を行う
   void Finalize();

   // ゴルフボールを転がす
   void Roll(const DirectX::SimpleMath::Vector2& direction, const float& force);

public:
   // 摩擦係数
   static const float FRICTION;
   // 最大移動速度
   static const float MAX_SPEED;

private:
   // DirectXグラフィックス
   Graphics* m_graphics;

   // ゴルフボールモデル
   DirectX::Model* m_model;
   // ゴルフボールの回転を示すクォータニオン
   DirectX::SimpleMath::Quaternion m_quaternion;
   // ゴルフボールの位置
   DirectX::SimpleMath::Vector2 m_position;
   // ゴルフボールの速度
   DirectX::SimpleMath::Vector2 m_velocity;
   // ゴルフボールの方向
   DirectX::SimpleMath::Vector2 m_heading;
   // ゴルフボールの質量
   float m_mass;
   // ゴルフボールの半径
   float m_radius;
};
#endif   // GOLF_BALL_DEFINED


GolfBallクラスを実装する

GolfBallクラスの宣言に続いて、GolfBallクラスのメンバー変数の定義とメンバー関数の実装をおこないます。

GolfBallクラスの初期化処理

コンストラクタの引数でゴルフボールのモデルへのポインタを取得します。GolfBallクラスに宣言した「摩擦係数」「最大移動速度」の定数を定義します。現在のところ、ゴルフボールの「質量」と「半径」はメンバー変数を宣言し、下記のように初期化しています。

  • 摩擦係数:           const float GolfBall::FRICTION = -0.02f

  • 最大移動速度:   const float GolfBall::MAX_SPEED = 3.0f


  • 質量:  m_mass = 0.45f

  • 半径:  m_radius = 2.13f

#include "pch.h"
#include "GolfBall.h"
#include "Common.h"

// 摩擦係数
const float GolfBall::FRICTION = -0.02f;
// 最大移動速度
const float GolfBall::MAX_SPEED = 3.0f;

// コンストラクタ
GolfBall::GolfBall(DirectX::Model* model)
   :
   m_model(model),																	// モデル
   m_quaternion{},																		// クォータニオン
   m_position(DirectX::SimpleMath::Vector2(0.0f, 0.0f)),	// 位置
   m_velocity(DirectX::SimpleMath::Vector2(0.0f, 0.0f)),	// 速度
   m_heading(DirectX::SimpleMath::Vector2(0.0f, 0.0f)),		// 向き
   m_mass(0.45f),						// 質量												// 質量
   m_radius(2.13f)						// 半径												// 半径
{
   // DirectXグラフィックスを取得する
   m_graphics = Graphics::GetInstance();
}


ゴルフボールを更新する

Update関数では、ゴルフボールの速度ベクトルから方向ベクトルを作り、方向ベクトルと摩擦係数の乗算結果を速度ベクトルから減算します。方向ベクトルからゴルフボールの回転軸を計算し、回転軸を基にゴルフボールの回転クォータニオンを生成します。次にゴルフボールの更新手順を示します。

  1. 速度ベクトルを向きベクトルに代入する

  2. 方向ベクトルに摩擦係数を掛けて速度ベクトルに加算する

  3. 位置ベクトルに速度ベクトルを加算する

  4. ゴルフボールの方向ベクトルからゴルフボールの回転軸を計算する

  5. ゴルフボールの回転軸からクォータニオンを生成する

// 更新する
void GolfBall::Update(const float& elapsedTime)
{
   using namespace DirectX::SimpleMath;
   UNREFERENCED_PARAMETER(elapsedTime);

   // 摩擦による減速の大きさより速度が速ければ減速させる
   if (m_velocity.Length() > GolfBall::FRICTION)
   {
      // 向きを設定する
      m_heading = m_velocity;
      // 摩擦により減速する
      m_velocity += m_heading * GolfBall::FRICTION;
      // 位置を更新する
      m_position += m_velocity;
      // ゴルフボールの回転軸を設定する
      Vector3 axis = Vector3(m_heading.y, 0.0f, -m_heading.x);
      // ゴルフボールが移動している場合
      if (m_velocity.Length())
      {
         // クォータニオンを生成する
         m_quaternion *= Quaternion::CreateFromAxisAngle(axis, m_velocity.Length() / m_radius);
      }
   }
}


ゴルフボールを描画する

ゴルフボールのスケール値から「スケール行列」、ゴルフボールの位置から「移動行列」、クォータニオンから「回転行列」を生成し、それらを乗算し、「ワールド行列」を生成します。描画プリミティブを開始し、モデルを描画し、描画プリミティブを終了します。次に描画手順を示します。

  1. ゴルフボールの「スケール行列」を生成する

  2. ゴルフボールの位置の「移動行列」を生成する

  3. ゴルフボールの回転クォータニオンから「回転行列」を生成する

  4. 「ワールド行列」を計算する

  5. 描画プリミティブを開始する

  6. ゴルフボールを描画する

  7. 描画プリミティブを終了する

// 描画する
void GolfBall::Render()
{
   using namespace DirectX::SimpleMath;

   // スケール行列を生成する
   Matrix scaleMatrix = Matrix::CreateScale(1.0f, 1.0f, 1.0f);
   // 移動行列を生成する
   Matrix translationMatrix = Matrix::CreateTranslation(m_position.x, m_radius, m_position.y);
   // 回転クォータニオンから回転行列を生成する
   Matrix rotationMatrix = Matrix::CreateFromQuaternion(m_quaternion);
   // ワールド行列を計算する
   Matrix worldMatrix = scaleMatrix * rotationMatrix * translationMatrix;

   // 描画プリミティブを開始する
   m_graphics->DrawPrimitiveBegin(m_graphics->GetViewMatrix(), m_graphics->GetProjectionMatrix());
   // ゴルフボールを描画する
   m_graphics->DrawModel(m_model, worldMatrix);
   // 描画プリミティブを終了する
   m_graphics->DrawPrimitiveEnd();
}


次回はグラフシーンでゴルフボールのインスタンスを生成し、ゴルフボールに向きと力を設定し、ゴルフボールを転がしてみましょう。


いいなと思ったら応援しよう!