ことはじめ

にほんごのれんしゅうにっき

3D学習帳 1

ワールド座標変換

ある3Dのモデルを3Dのフィールドにフィールドに設置したいとき、モデルの頂点座標をフィールドの座標に変換してやらないといけない。
ここで、モデルの座標をローカル座標といい、フィールドの座標をワールド座標という。
このローカル座標からワールド座標への変換をワールド座標変換と呼ぶ。

ワールド座標変換は、ローカル座標にある頂点を拡大縮小、回転、移動することで実現する。
それぞれの変換には行列を使います。移動行列は3x3では表現できないので4x4の同次座標系を使います。

拡大縮小

3Dのモデルが遠近法以外で大きくなったり小さくなったりすることはあまりないような気がする。
しかし、モデルの縮尺とフィールドの縮尺を合わせるときとかに使うんだろう。

拡大縮小行列Sは、縮尺をsとすると、

  S = \left(
    \begin{array}{cccc}
      s & 0 & 0 & 0 \\
      0 & s & 0 & 0 \\
      0 & 0 & s & 0 \\
      0 & 0 & 0 & 1 \\
    \end{array}
  \right)
となります。
ゼロが多くてキモイですね。

回転

キャラクターがローカル座標で-z方向を向いているとき、ワールド座標変換してやらないとフィールド上でもずっと-z方向を向いてしまいます。

回転行列はx軸回転、y軸回転、z軸回転の3つありそれぞれR_{x}, R_{y}, R_{z}、回転角を\thetaとすると、

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

  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)

  R_{z} = \left(
    \begin{array}{cccc}
      \cos\theta & -\sin\theta & 0 & 0 \\
      \sin\theta & \cos\theta & 0 & 0 \\
      0 & 0 & 1 & 0 \\
      0 & 0 & 0 & 1 \\
    \end{array}
  \right)
となります。

平行移動

ローカル座標の原点をワールド座標のある座標に対応させることでモデルの移動を実現します。

平行移動行列をTxyz方向の移動量をそれぞれt_{x}, t_{y}, t_{z}とすると、

  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)
となります。

ワールド変換!

ここまででワールド座標変換の準備ができたのでこれらを組み合わせてワールド変換行列をつくります。
まず回転行列をまとめてRとしておきましょう。
回転の順番は重要ですがここではめんどくさいので省略します。
そうするとワールド変換行列Rは、

W = SRT
となります。
ここで、平行移動を最後に行うことに注意しましょう。回転と拡大縮小は入れ替え可能です、多分。

ワールド変換座標が出来たので実際に頂点座標を変換してみます。
変換前の座標をp_{x}, p_{y}, p_{z}、変換後の座標をq_{x}, q_{y}, q_{z}とすると、

\left(
    \begin{array}{cccc}
      q_{x} &
      q_{y} &
      q_{z} &
      q_{w} &
    \end{array}
  \right) = 

\left(
    \begin{array}{cccc}
      p_{x} &
      p_{y} &
      p_{z} &
      1 &
    \end{array}
  \right)W
これでいけます。
q_{w}は今のところ使わないので無視していいです。
同次座標を使ったことによって生み出された澱、ここでは常に1になります。

長いのでいったん終了。初ブログだから気合入っちゃってるのよ、ゆるして。