数学
HALDay 19

3D入門してみて(拡大、縮小、移動、回転)

はじめに

どうも、harusann2です。HAL大阪のゲーム制作学科1年です。
卒業するまでに3Dゲームエンジンを作ることが目標です。

この記事はHAL Advent Calendar 2017の19日目の投稿です。
最近入門したばかりなので間違っているところがあるかもしれませんが、その場合コメントで指摘していただけると有り難いです。

3Dをやりたい!

当然ゲーム学科の人間なのでゲームを作りたいのですが今時のゲームは当然のように3Dです。
DirectXやOpenGL,WebGL,Vulkanなどを使用することで3D表示は簡単にできますが、実際内部でどういった処理を行い3D表示を実現しているのでしょうか?
というわけで実際にまだ途中ですが3DAPIを使わずにTypeScriptで3D表示に挑戦してみたので数パートに分けてその解説をしてみます。


今回解説するのは回転,移動,拡大です。

拡大、縮小、回転、移動

3Dはやはり数学が出てきます。
僕は高校に行っていないので非常に苦労しましたがやっぱり数学を避けることはできませんね。

ただ、行列などの解説をするのはしんどいので知らない方は他のサイトや本などで勉強してください。

拡大、縮小

\begin{pmatrix}
sx&0&0&0 \\
0&sy&0&0 \\
0&0&sz&0 \\
0&0&0&1 \\
\end{pmatrix}

移動

\begin{pmatrix}
1&0&0&tx \\
0&1&0&ty \\
0&0&1&tz \\
0&0&0&1 \\
\end{pmatrix}

X軸回転

\begin{pmatrix}
1&0&0&0 \\
0&\cos\theta&-\sin\theta&0 \\
0&\sin\theta&\cos\theta&0 \\
0&0&0&1 \\
\end{pmatrix}

Y軸回転

\begin{pmatrix}
\cos\theta&0&\sin\theta&0 \\
0&1&0&0 \\
-\sin\theta&0&\cos\theta&0 \\
0&0&0&1 \\
\end{pmatrix}

Z軸回転

\begin{pmatrix}
\cos\theta&-\sin\theta&0&0 \\
\sin\theta&\cos\theta&0&0 \\
0&0&1&0 \\
0&0&0&1 \\
\end{pmatrix}

です。
これと変換したい座標との内積を取るだけです。
拡大、縮小と移動はそのままですが回転が少し複雑です。

なお、Quaternionとか言うより良い回転方法があるらしいのですが現在理解していないので解説はしません。
今回説明する回転方法のデメリットとして向きたい方向に向くということが難しいのですがそれをQuaternionは解決しているそうです。

それはともかく、結論として僕が理解している簡単な回転行列はこのようになっています。
sinとかcosとかありますがこれは加法定理を利用しています。

3d2.png

$\triangle ocb$と$\triangle abd$は合同
なぜなら$\angle cdb$は$180^\circ$
三角形の角度の合計も$180^\circ$なので
$\angle cob = 180 - 90 - \angle cbo$
$\angle cob = 180 - 90 - \angle dba$
そして2つの角が決まればもう一つの角も決まるので全ての角が同じになり$\triangle ocb$と$\triangle abd$は合同になる
$|ob|$は$\cos\theta$
$|ab|$は$\sin\theta$
なお$||P||$は$P$の長さ
で$\triangle oPP'$と$\triangle ocb'$は相似なので

\frac{\|oc\|}{\cos\theta}=\frac{Px}{\|P\|}\qquad
\frac{\|cb\|}{\cos\theta}=\frac{Py}{\|P\|}\\
\frac{\|bd\|}{\sin\theta}=\frac{Px}{\|P\|}\qquad
\frac{\|ad\|}{\sin\theta}=\frac{Py}{\|P\|}

になり
変形すると

\|oc\|=\frac{Px\cos\theta}{\|P\|}\qquad
\|cb\|=\frac{Py\cos\theta}{\|P\|}\\
\|bd\|=\frac{Px\sin\theta}{\|P\|}\qquad
\|ad\|=\frac{Py\sin\theta}{\|P\|}

そしてQの座標は

\|P\|(\|oc\|-\|ad\|)=Qx\\
\|P\|(\|cb\|+\|bd\|)=Qy

これを当てはめると

\|P\|\left(\frac{Px\cos\theta}{\|P\|}-\frac{Py\sin\theta}{\|P\|}\right)=Qx\\
\|P\|\left(\frac{Px\sin\theta}{\|P\|}+\frac{Py\cos\theta}{\|P\|}\right)=Qy

簡単にして

Px\cos\theta-Py\sin\theta=Qx\\
Px\sin\theta+Py\cos\theta=Qy

この式を行列に入れたのが回転の行列です。

まとめ

数学って大変です。