したかみ ぶろぐ

Unity成分多め

3D数学の復習と実践(平行移動)

前回

shitakami.hatenablog.com

前回の記事で回転についてまとめたので、今回は平行移動についてやっていこうと思います。

今回も前回と同様にUnityのShaderで座標移動を実装していこうと思います。



4 × 4の行列

前回は3 × 3の行列を使って回転について解説しました。

3 × 3の行列は回転とスケーリングが出来ます。(前回、スケーリングについて解説するのを忘れてた)

では、平行移動するためにはどうするかというと4 × 4の行列を使用します。


T(\Delta x, \Delta y, \Delta z)
=
\begin{pmatrix} 
1 & 0 & 0 & \Delta x \\
0 & 1 & 0 & \Delta y \\
0 & 0 & 1 & \Delta z \\
0 & 0 & 0 & 1  \end{pmatrix}


この行列を掛けることで平行移動が出来ます。


\begin{pmatrix}
x & y & z & 1 
 \end{pmatrix} 
 T(\Delta x, \Delta y, \Delta z)
=
\begin{pmatrix} 
x + \Delta x & y + \Delta y & z + \Delta z & 1
  \end{pmatrix}



また、前回スケーリング→回転の順に計算をしました。そのあとに平行移動するので結果スケーリング→回転→平行移動の順で計算します。

実装

シェーダーに平行移動を実装します。

    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}

        _PosX ("Pos X", float) = 0
        _PosY ("Pos Y", float) = 0
        _PosZ ("Pos Z", float) = 0

        _ScaleX ("Scale X", float) = 1
        _ScaleY ("Scale Y", float) = 1
        _ScaleZ ("Scale Z", float) = 1

        _ThetaX ("Theta X", float) = 0
        _ThetaY ("Theta Y", float) = 0
        _ThetaZ ("Theta Z", float) = 0
    }
. . . . . .
. . . . . .
                float4x4 pos = float4x4(
                    float4(1, 0, 0, _PosX),
                    float4(0, 1, 0, _PosY),
                    float4(0, 0, 1, _PosZ),
                    float4(0, 0, 0, 1));

                v.vertex = mul(scale, v.vertex);
                v.vertex = mul(rotX, v.vertex);
                v.vertex = mul(rotY, v.vertex);
                v.vertex = mul(rotZ, v.vertex);
                v.vertex = mul(pos, v.vertex);


                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }


結果が次のgifになります。

f:id:vxd-naoshi-19961205-maro:20191202012103g:plain



因みに、以下のように書き換えることも出来ます。普段使いではこのように書いたほうが分かり易いかもしれません。

                v.vertex = mul(scale, v.vertex);
                v.vertex = mul(rotX, v.vertex);
                v.vertex = mul(rotY, v.vertex);
                v.vertex = mul(rotZ, v.vertex);
                v.vertex.x += _PosX;
                v.vertex.y += _PosY;
                v.vertex.z += _PosZ;


                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            } 



最後に

平行移動については簡単にまとめました。

次はQuaternionについて勉強しようと思います。恐らく滅茶苦茶大変になると思いますが、頑張ります。


追記

次回の内容はロドリゲスの回転公式です。その次にQuaternionをまとめましたが、その前に一読してほしいです。

shitakami.hatenablog.com

shitakami.hatenablog.com