Skip to main content

AI モンスターの知能

同次変換・アフィ変換 練習問題スターに視覚を与える

2D・3DisFindPlayer / DirectX11形式は誰が決めているのか?


導入:右から掛けるルールと左から掛けるルール

1. 前回までの確認

3Dグラフィック前回、モンターの行列計算動を if文 は、資料やライブラリによって点と行列の掛け切り替える考えが違うを学びました

大きく分けると例えば、次の2種類があるような処理です。

if (isAttackRange)
{
    Attack();
}
else if (isFindPlayer)
{
    ChasePlayer();
}
else
{
    Idle();
}

この処理では、モンスターは次のように行動します

方式条件 点の書き方掛け算の形よく見る場面行動
列ベクトル方式攻撃範囲にいる 縦に書く$$P' = M P$$数学の教科書、OpenGL系の説明攻撃する
行ベクトル方式プレイヤーを見つけている 横に書く追いかける
どちらでもない $$P' = P M$$DirectX系の説明待機する

このプリントでは、最終的にDirectX11でよく使う行ベクトル方式で練習する。
ただし、最初に2つの違いを確認しておく。


1. 列ベクトル方式

列ベクトル方式では、点を縦に書く。

2Dの点 $P(x, y)$ は、同次座標で次のように、条件によって行動を変えることで、モンスターが考えて動いているように見えま

$$ P = \left( \begin{array}{c} x \\ y \\ 1 \end{array} \right) $$

変換後の点は、行列を左から掛けて求める。

$$ P' = M P $$

つまり、行列が左、点が右にある


2. 列ベクトル方式の平行移動ここで問い

列ベクトル方式で、x方向に $t_x$、y方向に $t_y$ 平行移動する行列は次の変数注目してください。

isFindPlayer

これは、

プレイヤーを見つけていか?

を表すフラグです

$$ T = \left( \begin{array}{ccc} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{array} \right) $$しかし、ここで考えるべきことがあります。


isFindPlayer は誰が決めているのか?


点に掛けるプログラムの中で、

if (isFindPlayer)

、次のようになる書くことはできます

$$しかし、isFindPlayer P'true になる理由を作らなければ、モンスターはプレイヤーを見つけることができません。

つまり、

isFindPlayer = Ttrue;
P
$$

$$ \left( \begin{array}{c} x' \\ y' \\ 1 \end{array} \right)

\left( \begin{array}{ccc} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{array} \right) \left( \begin{array}{c} x \\ y \\ 1 \end{array} \right) $$

実際に掛け算すると、

$$ x' = 1 \times x + 0 \times y + t_x \times 1 $$

$$ y' = 0 \times x + 1 \times y + t_y \times 1 $$

したがって、

$$ x' = x + t_x $$

$$ y' = y + t_y $$

になる条件を、こちらで作る必要があります


3. 行ベクトル方式ゲームAIには「知覚」が必要

モンスターがベクトル方式で動を決めるには、まずゲームの状況横に書く。

2Dの点 $P(x, y)$ は、同次座標で次のように表知る必要がありま

$$ P = \left( \begin{array}{ccc} x & y & 1 \end{array} \right) $$

変換後の点は、点を左から行列に掛けて求める。

$$ P' = P M $$

つまり、点が左、行列が右にある。


4. 行ベクトル方式の平行移動

行ベクトル方式で、x方向に $t_x$、y方向に $t_y$ 平行移動する行列は次の形になる。

$$ T = \left( \begin{array}{ccc} 1 & 0 & 0 \\ 0 & 1 & 0 \\ t_x & t_y & 1 \end{array} \right) $$

点に掛けると、次のようになる。

$$ P' = P T $$

$$ \left( \begin{array}{ccc} x' & y' & 1 \end{array} \right)

\left( \begin{array}{ccc} x & y & 1 \end{array} \right) \left( \begin{array}{ccc} 1 & 0 & 0 \\ 0 & 1 & 0 \\ t_x & t_y & 1 \end{array} \right) $$

実際に掛け算すると、

$$ x' = x \times 1 + y \times 0 + 1 \times t_x $$

$$ y' = x \times 0 + y \times 1 + 1 \times t_y $$

したがって、

$$ x' = x + t_x $$

$$ y' = y + t_y $$

になる。


5. 同じ変換でも行列の形が違う

同じ「x方向に $t_x$、y方向に $t_y$ 平行移動」でも、列ベクトル方式と行ベクトル方式では、行列の形が違う。

列ベクトル方式

$$ \left( \begin{array}{ccc} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{array} \right) $$

行ベクトル方式

$$ \left( \begin{array}{ccc} 1 & 0 & 0 \\ 0 & 1 & 0 \\ t_x & t_y & 1 \end{array} \right) $$

列ベクトル方式では、平行移動は右端の列に入る。
行ベクトル方式では、平行移動は下の行に入る。


6. 掛け算のやり方の違い

列ベクトル方式

列ベクトル方式では、

$$ P' = M P $$

である

例えば、

  • プレイヤーが近くにいる
  • プレイヤーが前方にいる
  • プレイヤーとの間に壁がない
  • プレイヤーが音を立てた
  • プレイヤーが攻撃してきた

$$ \left( \begin{array}{ccc} a & b & c \\ d & e & f \\ g & h & i \end{array} \right) \left( \begin{array}{c} x \\ y \\ 1 \end{array} \right) $$などです。

このように、AIがゲームの状況計算知る仕組みを 知覚 と呼びまると、

$$ x' = ax + by + c $$

$$ y' = dx + ey + f $$

$$ w' = gx + hy + i $$

になる


行ベクトル方式

4. 人間の「見る」とAIの「見る」は違う

行ベクトル人間は目で映像を見ています。

しかし、ゲームAIは本当に画面を見ているわけではありません。

ゲームAIは、次のような数値や条件を使って「見えているか」を判定します。

距離は近いか?
前式でにいるか?
壁に隠れていないか?

つまり、ゲームAIの視覚とは、

$$

画像を見ること
P' = P M
$$

はなく、

条件を満たしたら「見えてい」とする処理

です。


5. まず一番簡単な視覚を作る

最初は、距離だけで考えます

例えば、

プレイヤーが10m以内にいたら発見

$$ \left( \begin{array}{ccc} x & y & 1 \end{array} \right) \left( \begin{array}{ccc} a & b & c \\ d & e & f \\ g & h & i \end{array} \right) $$というルールにします。

この場合、モンスターはプレイヤーとの距離計算調べます。

VECTOR toPlayer = VSub(playerPos, enemyPos);
float distance = VSize(toPlayer);

if (distance < VIEW_DISTANCE)
{
    isFindPlayer = true;
}
else
{
    isFindPlayer = false;
}

ここで、VIEW_DISTANCE は視界距離です。

const float VIEW_DISTANCE = 10.0f;

6. 距離だけの視覚の問題点

距離だけで判定すると、

$$ x' = xa + yd + 1g $$

$$ y' = xb + ye + 1h $$

$$ w' = xc + yf + 1i $$

り単純なAIになります

同じ行列例えば、次のような問題があります。


問題1:後ろいても見つかる

距離だけで判定すると、プレイヤーがモンスターの後ろにいても見つかってしまいます。

プレイヤー
   ↓
モンスター → 前を向いている

本当なら、モンスターの後ろにいるプレイヤーは見えないはずです。

でも距離だけで判定しいると、近ければ見つかります。


問題2:壁越しで見つかる

距離だけで判定するとどち壁の向こうにいるプレイヤーも見つかってしまいます。

モンスター |壁| プレイヤー

本当な、壁があるので見えないはずです。

でも距離だけで判定していると、近ければ見つら掛けるかで使われる成分が変わるります


7. 合成変換の順番の違い視覚に必要な条件

より自然な視覚を作る対して、次の順番3つを考えます。

1. 距離
2. 向き
3. 障害物

8. 条件1:距離

まずは距離変換したす。

プレイヤーが遠すぎるなら見えな

これは分かりやい条件です。

if (distance > VIEW_DISTANCE)
{
    isFindPlayer = false;
}

9. 条件2:向き

次に、プレイヤーがモンスターの前方にいるかを調べます。

モンスターには向きがあります。

モンスター → 前方

プレイヤーが前方にいれば見える。

    モンスター 
  1. 拡大縮小 $S$
  2. プレイヤー
  3. 回転
  4. $R$

    しかし、プレイヤーが後ろにいるなら見えません。

  5. 平行移動
    プレイヤー $T$
モンスター

10. 前方にいるかをどう調べるか

ここで使うのが 内積 です。

必要なベクトルは2つです。

モンスターの前向
モンスターからプレイヤーへ場合方向

11. モンスターからプレイヤーへの方向

まず、モンスターからプレイヤーへのベクトル方式では、を求めます。

$$

VECTOR P'toPlayer = MVSub(playerPos, PenemyPos);
$$

次に、長さを1にします。

float distance = VSize(toPlayer);
VECTOR dirToPlayer = VScale(toPlayer, 1.0f / distance);

この dirToPlayer が、モンスターから見たプレイヤーの方向あるす。


12. モンスターの前方向

次に、モンスターの前方向を用意します

実際の計算は例として、Y軸回転から前方向を作るなら、次のようになります。

VECTOR forward =
{
    sinf(enemyRotY),
    0.0f,
    cosf(enemyRotY)
};

ただし、モデルの正面方向や座標系によって、sinf と cosf の使い方は変わことがあります。


13. 内積で角度を調べる

2つのベクトルの内積を取ります。

float dot = VDot(forward, dirToPlayer);

dot の値は、だいたい次のように考えられます。

dotの値意味
1.0 に近い正面にいる
0.0 に近い横にいる
-1.0 に近い後ろにいる

14. 視野角の判定

例えば、次のようにします。

const float VIEW_DOT = 0.5f;

if (dot > VIEW_DOT)
{
    isFindPlayer = true;
}
else
{
    isFindPlayer = false;
}

dot > 0.5f なら、前方のある範囲内にいると判断できます。


15. VIEW_DOT の目安

条件見える範囲の目安
dot > 0.5f前方約120度
dot > 0.707f前方約90度
dot > 0.866f前方約60度

数値を大きくすると、視野が狭くなります

$$数値を小さくすると、視野が広くなります。

P'

16. 距離と向きを組み合わせる

距離と向きを組み合わせると、次のような判定になります。

bool CheckCanSeePlayer()
{
    VECTOR toPlayer = TVSub(playerPos, RenemyPos);
    Sfloat Pdistance $$= VSize(toPlayer);

    if (distance > VIEW_DISTANCE)
    {
        return false;
    }

    if (distance < 0.001f)
    {
        return true;
    }

    VECTOR dirToPlayer = VScale(toPlayer, 1.0f / distance);

    VECTOR forward =
    {
        sinf(enemyRotY),
        0.0f,
        cosf(enemyRotY)
    };

    float dot = VDot(forward, dirToPlayer);

    if (dot < VIEW_DOT)
    {
        return false;
    }

    return true;
}

この関数は、

プレイヤーが見えているなら true
見えていないなら false

を返します。


17. 条件3:障害物

まだ問題があります。

距離が近くて、前方にいても、壁の向こうにいるなら本当は見えません。

モンスター ---- 壁 ---- プレイヤー

この場合は、見えないようにしたいです。


18. 壁で見えない処理

考え方は単純です。

モンスターからプレイヤーまで線を引く
↓
途中に壁があるか調べる
↓
壁があれば見えない
↓
壁がなければ見える

このような判定を、レイ判定やライン判定と呼びます。


19. 疑似コード

bool isHitWall = CheckLineHitWall(enemyPos, playerPos);

if (isHitWall)
{
    return false;
}

CheckLineHitWall は、敵とプレイヤーの間に壁があるか調べる処理だと考えてください。


20. 最終的な視覚判定

距離、向き、壁を組み合わせると、次のような流れになります。

bool CheckCanSeePlayer()
{
    VECTOR toPlayer = VSub(playerPos, enemyPos);
    float distance = VSize(toPlayer);

    // 遠すぎるなら見えない
    if (distance > VIEW_DISTANCE)
    {
        return false;
    }

    // ほぼ同じ位置なら見えている扱い
    if (distance < 0.001f)
    {
        return true;
    }

    // 方向を求める
    VECTOR dirToPlayer = VScale(toPlayer, 1.0f / distance);

    // モンスターの前方向
    VECTOR forward =
    {
        sinf(enemyRotY),
        0.0f,
        cosf(enemyRotY)
    };

    // 前方にいるか調べる
    float dot = VDot(forward, dirToPlayer);

    if (dot < VIEW_DOT)
    {
        return false;
    }

    // 壁があれば見えない
    if (CheckLineHitWall(enemyPos, playerPos))
    {
        return false;
    }

    return true;
}

21. 前回のAIに接続する

視覚判定ができたら、前回のAIに接続できます。

isFindPlayer = CheckCanSeePlayer();

if (isAttackRange)
{
    Attack();
}
else if (isFindPlayer)
{
    ChasePlayer();
}
else
{
    Idle();
}

これで、

見えたら追いかける
見えなければ待機する

というモンスターになります。


22. 何がAIらしくなるのか

距離だけで判定していたときは、

近ければ必ず見つかる

という動きでした。

しかし、視野角や壁判定を入れると、次のようになります。

後ろに回ると気づかれない
壁に隠れると見つからない
正面に出ると追いかけてくる

このようなルールがあると、プレイヤーは、

敵に見つかった
敵から隠れた
敵の背後を取った

と感じやすくなります。

つまり、合成行列は、

$$ M = T R S $$

である。

行列のAIが少し賢くた目としては、後に実行えまる変換ほど左側に来る


行ベクトル方式の場合

行ベクトル方式では、

$$ P' = P M $$

である。

実際の計算は次のようになる。

$$ P' = P S R T $$

つまり、合成行列は、

$$ M = S R T $$

である。

行列の見た目としては、実行したい順番に左から右へ並べればよい


8.23. このプリントで使うルール重要な考え方

ゲームAIは、本当に人間プリントように世界を理解しているわけではDirectX11形式ありません。

かし、次のルールような情報を使うこと統一、考えているように見せることができま

点は行ベクトルで書く

距離
方向
角度
障害物
時間
状態

$$ P = \left( \begin{array}{ccc} x & y & 1 \end{array} \right) $$

AIは、世界をそのま理解しているのでなく

$$ P = \left( \begin{array}{cccc} x & y & z & 1 \end{array} \right) $$

点は左から行列ゲーム必要な情報だ

$$ P' = P M $$

合成変換は、実行を取り出て判断して順番に行列を並べる

例えば、

  1. 拡大縮小
  2. 回転
  3. 平行移動

なら、

$$ M = S R T $$

であるます


2Dの同次座標まとめ

2次元今回点 $P(x, y)$ は、同次座標でポイントは次のように表通りです。

$$

isFindPlayer Pは勝手に決まらない
=
\left(
AIには知覚が必要
\begin{array}{ccc}
x & y & 1 \end{array} \right) $$

2Dのアフィン変換行列

ゲームAIの視覚、DirectX11形式画像を見ることでは次の形ない
距離・向き・壁で「見えている」を作る
見えているかどうかをフラグなる。

して、行動分岐に使う

$$ M = \left( \begin{array}{ccc} a & b & 0 \\ c & d & 0 \\ t_x & t_y & 1 \end{array} \right) $$


2Dの基本変換行列

平行移動

$$ T = \left( \begin{array}{ccc} 1 & 0 & 0 \\ 0 & 1 & 0 \\ t_x & t_y & 1 \end{array} \right) $$

拡大縮小

$$ S = \left( \begin{array}{ccc} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & 1 \end{array} \right) $$

原点中心の回転

このプリントでは、2D回転は反時計回りを正とする。

$$ R = \left( \begin{array}{ccc} \cos\theta & \sin\theta & 0 \\ -\sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{array} \right) $$


第1部:2D同最後の確認問題

問1

変換のフラグは何を表しているか説明しなさい。

bool isFindPlayer;

題1:2D平行移動

点 $P(2, 3)$ を、次のように平行移動する。

  • x方向に $+4$
  • y方向に $-1$

問い

  1. 平行移動行列 $T$ を書け。
  2. 次の計算を行い、変換後の座標を求めよ。

$$ P' = P T $$

解答欄

$$ T = \left( \begin{array}{ccc} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{array} \right) $$

変換後の座標:

$$ (\quad,\quad) $$


問題2:2D拡大縮小

点 $P(2, 3)$ を、次のように拡大縮小する。

  • x方向に $3$ 倍
  • y方向に $2$ 倍

問い

  1. 拡大縮小行列 $S$ を書け。
  2. 次の計算を行い、変換後の座標を求めよ。

$$ P' = P S $$

解答欄

$$ S = \left( \begin{array}{ccc} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{array} \right) $$

変換後の座標:

$$ (\quad,\quad) $$


問題3:2D回転

点 $P(1, 0)$ を、原点を中心に反時計回りに $90^\circ$ 回転する。

$$ \cos 90^\circ = 0 $$

$$ \sin 90^\circ = 1 $$

問い

  1. 回転行列 $R$ を書け。
  2. 次の計算を行い、変換後の座標を求めよ。

$$ P' = P R $$

解答欄

$$ R = \left( \begin{array}{ccc} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{array} \right) $$

変換後の座標:

$$ (\quad,\quad) $$


問題4:2D合成変換

点 $P(1, 2)$ に対して、次の順番で変換する。

  1. x方向に $2$ 倍、y方向に $3$ 倍する
  2. x方向に $+5$、y方向に $-1$ 平行移動する

DirectX11形式なので、合成行列は次の順番になる。

$$ M = S T $$

問い

  1. 拡大縮小行列 $S$ を書け。
  2. 平行移動行列 $T$ を書け。
  3. 合成行列 $M = S T$ を求めよ。
  4. 点 $P$ の変換後の座標を求めよ。

解答欄

$$ S = \left( \begin{array}{ccc} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{array} \right) $$

$$ T = \left( \begin{array}{ccc} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{array} \right) $$

$$ M = S T = \left( \begin{array}{ccc} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{array} \right) $$

変換後の座標:

$$ (\quad,\quad) $$


問題5:2D合成変換と順番の違い

点 $P(1, 1)$ に対して、次の2通りの変換を行う。

A

  1. x方向に $+3$、y方向に $0$ 平行移動する
  2. 全体を $2$ 倍に拡大する

B

  1. 全体を $2$ 倍に拡大する
  2. x方向に $+3$、y方向に $0$ 平行移動する

問い

  1. Aの合成行列 $M_A$ を求めよ。
  2. Bの合成行列 $M_B$ を求めよ。
  3. AとBそれぞれの変換後の座標を求めよ。
  4. 結果が違う理由を説明せよ。

解答欄

Aの合成行列:

$$ M_A = \left( \begin{array}{ccc} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{array} \right) $$

Aの変換後:

$$ (\quad,\quad) $$

Bの合成行列:

$$ M_B = \left( \begin{array}{ccc} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{array} \right) $$

Bの変換後:

$$ (\quad,\quad) $$

理由:


第2部:3D同次変換


3Dの同次座標

3次元の点 $P(x, y, z)$ は、同次座標では次のように表す。

$$ P = \left( \begin{array}{cccc} x & y & z & 1 \end{array} \right) $$

3Dのアフィン変換行列は、DirectX11形式では次の形になる。

$$ M = \left( \begin{array}{cccc} a & b & c & 0 \\ d & e & f & 0 \\ g & h & i & 0 \\ t_x & t_y & t_z & 1 \end{array} \right) $$


3Dの基本変換行列

平行移動

$$ T = \left( \begin{array}{cccc} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ t_x & t_y & t_z & 1 \end{array} \right) $$

拡大縮小

$$ S = \left( \begin{array}{cccc} s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 & 1 \end{array} \right) $$

Y軸回転

このプリントでは、DirectXの左手系を前提とする。

$$ R_y = \left( \begin{array}{cccc} \cos\theta & 0 & -\sin\theta & 0 \\ 0 & 1 & 0 & 0 \\ \sin\theta & 0 & \cos\theta & 0 \\ 0 & 0 & 0 & 1 \end{array} \right) $$

$90^\circ$ の場合は次のようになる。

$$ R_y = \left( \begin{array}{cccc} 0 & 0 & -1 & 0 \\ 0 & 1 & 0 & 0 \\ 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{array} \right) $$


問題6:3D平行移動

点 $P(1, 2, 3)$ を、次のように平行移動する。

  • x方向に $+4$
  • y方向に $-2$
  • z方向に $+1$

問い

  1. 平行移動行列 $T$ を書け。
  2. 次の計算を行い、変換後の座標を求めよ。

$$ P' = P T $$

解答欄

$$ T = \left( \begin{array}{cccc} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{array} \right) $$

変換後の座標:

$$ (\quad,\quad,\quad) $$


問題7:3D拡大縮小

点 $P(1, 2, 3)$ を、次のように拡大縮小する。

  • x方向に $2$ 倍
  • y方向に $3$ 倍
  • z方向に $4$ 倍

問い

  1. 拡大縮小行列 $S$ を書け。
  2. 次の計算を行い、変換後の座標を求めよ。

$$ P' = P S $$

解答欄

$$ S = \left( \begin{array}{cccc} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{array} \right) $$

変換後の座標:

$$ (\quad,\quad,\quad) $$


問題8:3D Y軸回転

点 $P(1, 0, 0)$ を、Y軸まわりに $90^\circ$ 回転する。

問い

  1. Y軸回転行列 $R_y$ を書け。
  2. 次の計算を行い、変換後の座標を求めよ。

$$ P' = P R_y $$

解答欄

$$ R_y = \left( \begin{array}{cccc} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{array} \right) $$

変換後の座標:

$$ (\quad,\quad,\quad) $$


問題9:3D合成変換

点 $P(1, 2, 3)$ に対して、次の順番で変換する。

  1. 全体を $2$ 倍に拡大する
  2. Y軸まわりに $90^\circ$ 回転する
  3. x方向に $+3$、y方向に $+1$、z方向に $+2$ 平行移動する

DirectX11形式なので、合成行列は次の順番になる。

$$ M = S R_y T $$

問い

  1. 拡大縮小行列 $S$ を書け。
  2. Y軸回転行列 $R_y$ を書け。
  3. 平行移動行列 $T$ を書け。
  4. 合成行列 $M = S R_y T$ を求めよ。
  5. 点 $P$ の変換後の座標を求めよ。

解答欄

$$ S = \left( \begin{array}{cccc} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{array} \right) $$

$$ R_y = \left( \begin{array}{cccc} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{array} \right) $$

$$ T = \left( \begin{array}{cccc} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{array} \right) $$

$$ M = S R_y T = \left( \begin{array}{cccc} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{array} \right) $$

変換後の座標:

$$ (\quad,\quad,\quad) $$


問題10:3D合成変換と順番の違い

点 $P(1, 0, 0)$ に対して、次の2通りの変換を行う。

A

  1. x方向に $+5$ 平行移動する
  2. Y軸まわりに $90^\circ$ 回転する

B

  1. Y軸まわりに $90^\circ$ 回転する
  2. x方向に $+5$ 平行移動する

問い

  1. Aの合成行列 $M_A$ を求めよ。
  2. Bの合成行列 $M_B$ を求めよ。
  3. AとBそれぞれの変換後の座標を求めよ。
  4. 結果が違う理由を説明せよ。

解答欄

Aの合成行列:

$$ M_A = \left( \begin{array}{cccc} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{array} \right) $$

Aの変換後:

$$ (\quad,\quad,\quad) $$

Bの合成行列:

$$ M_B = \left( \begin{array}{cccc} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{array} \right) $$

Bの変換後:

$$ (\quad,\quad,\quad) $$

理由:


解答例


問題1

$$ T = \left( \begin{array}{ccc} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 4 & -1 & 1 \end{array} \right) $$

答え:

$$ (6, 2) $$


問題2

$$ S = \left( \begin{array}{ccc} 3 & 0 & 0 \\ 0 & 2 & 0 \\ 0 & 0 & 1 \end{array} \right) $$

答え:

$$ (6, 6) $$


距離だけでプレイヤーを発見するAIには、どんな問題3

がありますか。

$$ R = \left( \begin{array}{ccc} 0 & 1 & 0 \\ -1 & 0 & 0 \\ 0 & 0 & 1 \end{array} \right) $$

答え:

$$ (0, 1) $$


問題4

$$ S = \left( \begin{array}{ccc} 2 & 0 & 0 \\ 0 & 3 & 0 \\ 0 & 0 & 1 \end{array} \right) $$

$$ T = \left( \begin{array}{ccc} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 5 & -1 & 1 \end{array} \right) $$

$$ M = S T = \left( \begin{array}{ccc} 2 & 0 & 0 \\ 0 & 3 & 0 \\ 5 & -1 & 1 \end{array} \right) $$

答え:

$$ (7, 5) $$


問題5

Aは、平行移動してから拡大するので、

$$ M_A = T S $$

$$ M_A = \left( \begin{array}{ccc} 2 & 0 & 0 \\ 0 & 2 & 0 \\ 6 & 0 & 1 \end{array} \right) $$

答え:

$$ (8, 2) $$

Bは、拡大してから平行移動するので、

$$ M_B = S T $$

$$ M_B = \left( \begin{array}{ccc} 2 & 0 & 0 \\ 0 & 2 & 0 \\ 3 & 0 & 1 \end{array} \right) $$

答え:

$$ (5, 2) $$

平行移動の前に拡大するか、後に拡大するかで、移動量も拡大2つ書きなれるかどうかが変わる


題63

$$ T = \left( \begin{array}{cccc} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 4 & -2 & 1 & 1 \end{array} \right) $$

答え:

$$ (5, 0, 4) $$モンスターの前方にプレイヤーがいるかを調べるために使う計算は何ですか。


題74

$$ S = \left( \begin{array}{cccc} 2 & 0 & 0 & 0 \\ 0 & 3 & 0 & 0 \\ 0 & 0 & 4 & 0 \\ 0 & 0 & 0 & 1 \end{array} \right) $$

壁の向こうにいるプレイヤーを見

$$ (2, 6, 12) $$ないようにするには、どのような判定が必要ですか。


題85

$$次の処理の意味を説明しなさい。

R_y
isFindPlayer = \left(CheckCanSeePlayer();
\begin{array}{cccc}
0 & 0 & -1 & 0 \\
0 & 1 & 0 & 0 \\
1 & 0 & 0 & 0 \\
0 & 0 & 0 & 1
\end{array}
\right)
$$

答え:

$$ (0, 0, -1) $$


問題9

$$ S = \left( \begin{array}{cccc} 2 & 0 & 0 & 0 \\ 0 & 2 & 0 & 0 \\ 0 & 0 & 2 & 0 \\ 0 & 0 & 0 & 1 \end{array} \right) $$

$$ R_y = \left( \begin{array}{cccc} 0 & 0 & -1 & 0 \\ 0 & 1 & 0 & 0 \\ 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{array} \right) $$

$$ T = \left( \begin{array}{cccc} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 3 & 1 & 2 & 1 \end{array} \right) $$

$$ M = S R_y T = \left( \begin{array}{cccc} 0 & 0 & -2 & 0 \\ 0 & 2 & 0 & 0 \\ 2 & 0 & 0 & 0 \\ 3 & 1 & 2 & 1 \end{array} \right) $$

答え:

$$ (9, 5, 0) $$


問題10

Aは、平行移動してから回転するので、

$$ M_A = T R_y $$

$$ M_A = \left( \begin{array}{cccc} 0 & 0 & -1 & 0 \\ 0 & 1 & 0 & 0 \\ 1 & 0 & 0 & 0 \\ 0 & 0 & -5 & 1 \end{array} \right) $$

答え:

$$ (0, 0, -6) $$

Bは、回転してから平行移動するので、

$$ M_B = R_y T $$

$$ M_B = \left( \begin{array}{cccc} 0 & 0 & -1 & 0 \\ 0 & 1 & 0 & 0 \\ 1 & 0 & 0 & 0 \\ 5 & 0 & 0 & 1 \end{array} \right) $$

答え:

$$ (5, 0, -1) $$

平行移動してから回転すると、移動後の位置全体が原点の周りを回転する。
回転してから平行移動すると、向きだけを変えてから指定方向に移動する。


確認ポイント発展課題

DirectX11形式

合成順

ようなモンスターを考えなさい。

普段は巡回している。
プレイヤーが視界に入ったら追いかける。
壁の向こうに逃げられたら見失う。
見失ったら、その場で3秒間探す。
それでも見つからなければ巡回に戻る。

このモンスターに必要なフラグ行ベクトルで扱う場合、

$$ P' = P M $$

である考えなさい

そのため、変換順が例:

    bool 
  1. 拡大縮小
  2. isFindPlayer;
  3. 回転
  4. bool
  5. 平行移動
  6. isLostPlayer;
bool isSearching; bool isPatrol;

さらに、どのようら、

順番で

$$if文 M = S R T $$

を書けばよいか考えさい


よくある間違い

列ベクトル形式の感覚で、

$$ M = T R S $$

と書くと、DirectX11形式では変換順が逆になってしまう。

このプリントでは、常に

$$ P' = P M $$

として計算する。