DirectX ボールを転がす1
これまでのところでグラフィックアセットを利用可能になりました。これからはDirectX Graphicsを活用して「ゴルフボールを転がす」プログラムを作成してみましょう。
DirectX TKは右手系
3Dグラフィックスのプログラミングでは、左手系(Left Handed System)と右手系(Right Handed System)の座標系を使用します。右手系の場合、下図のようにx軸とy軸の正の方向は左手系と同じですが、z軸の正方向が手前の方向になります。DirectX9の頃の3D座標系は左手系でしたが、DirectX11、12は右手系と左手系の両方が使用できます。DirectX TKはDirectX11、12に対応していますが、右手系です。
ゴルフボールを転がすアプリの座標系を次に示します。
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関数では、ゴルフボールの速度ベクトルから方向ベクトルを作り、方向ベクトルと摩擦係数の乗算結果を速度ベクトルから減算します。方向ベクトルからゴルフボールの回転軸を計算し、回転軸を基にゴルフボールの回転クォータニオンを生成します。次にゴルフボールの更新手順を示します。
速度ベクトルを向きベクトルに代入する
方向ベクトルに摩擦係数を掛けて速度ベクトルに加算する
位置ベクトルに速度ベクトルを加算する
ゴルフボールの方向ベクトルからゴルフボールの回転軸を計算する
ゴルフボールの回転軸からクォータニオンを生成する
// 更新する
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);
}
}
}
ゴルフボールを描画する
ゴルフボールのスケール値から「スケール行列」、ゴルフボールの位置から「移動行列」、クォータニオンから「回転行列」を生成し、それらを乗算し、「ワールド行列」を生成します。描画プリミティブを開始し、モデルを描画し、描画プリミティブを終了します。次に描画手順を示します。
ゴルフボールの「スケール行列」を生成する
ゴルフボールの位置の「移動行列」を生成する
ゴルフボールの回転クォータニオンから「回転行列」を生成する
「ワールド行列」を計算する
描画プリミティブを開始する
ゴルフボールを描画する
描画プリミティブを終了する
// 描画する
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();
}
次回はグラフシーンでゴルフボールのインスタンスを生成し、ゴルフボールに向きと力を設定し、ゴルフボールを転がしてみましょう。