【UnityShader】ロドリゲスの回転公式 【2】#82
前回の成果
ロドリゲスの回転公式のベクトル表現を理解した。
今回やること
ロドリゲスの回転公式のベクトル表現を行列で表現します。
正射影ベクトル
まずは、のを行列表現します。
そのために、ベクトル射影の行列表現というものを使用します。
公式は以下となります。
では証明していこうと思います。
証明
以下の画像を用いて証明します。
を求める
まず、求めたいベクトルをと置きます。
とは平行ですので、実数を利用すると
とすることができます。
との内積
次に内積について考えます。
ですので、以下となります。
実数を求める
とを求めることができたので、を求めます。
より、
代入する
これでを求めることができました。
なので以下となり、証明完了です。
正射影ベクトルの行列表現
正射影ベクトルの原理が理解できたので、これを行列で表します。
ベクトル射影の表現行列:より引用
ベクトルのベクトルへの射影
ベクトルのベクトルへの射影は以下となります。
正射影ベクトルの証明や、行列表現が長かったため忘れがちですが、
これにより、を行列表現することができます。
より、
また、この行列は転置行列ですので以下のような表し方もできます。
ベクトル積の表現行列
のを行列表現しました。
最後にを行列表現します。
の行列表現
ベクトル同士の乗算ですので、外積を表しています。
また、この行列は歪対称行列ですので以下で表すこともできます。
これでを行列表現できます。
の行列表現
長くなりましたが、これでロドリゲスの回転行列を表すことができます。
画像をもう一度出してから行列に置き換えていきます。
ロドリゲスのの回転公式の表現行列:より引用
位置ベクトルを角だけ回転させる回転行列をとします。
そうすると、回転後の位置ベクトルは以下で表されます。
次に、ロドリゲスの回転公式のベクトル表現より以下が定義されます。
そして、ベクトル射影の行列表現より以下となります。
更に、ベクトル積の行列表現により以下になります。
ベクトル射影の行列表現と、ベクトル積の行列表現により、ロドリゲスの回転公式のベクトル表現は以下に置き換えることができます。
は単位行列です。
よって、以下でロドリゲスの回転公式を行列表現できます。
これでロドリゲスの回転公式の行列表現が求めることができました。
結果
Thetaを変更することによって、Axisの軸で回転すれば成功です。
inspector
ソースコードにコメントを付与
Shader "Unlit/RodriguesRotation" { Properties { _MainTex ("Texture", 2D) = "white" {} _Axis ("Axis", Vector) = (0, 0, 0, 0) _Theta ("Theta", float) = 0 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; fixed4 _Axis; float _Theta; // 回転 fixed3 rotate(fixed3 pos, fixed3 axis, float theta) { fixed3 axisN = normalize(axis); // 0行列を回避 if (length(axisN) < 0.001) { return pos; } half radTheta = radians(theta); fixed sinTheta = sin(radTheta); fixed cosTheta = cos(radTheta); fixed a = 1.0 - cosTheta; // ロドリゲスの回転公式 fixed3x3 m = fixed3x3 ( axisN.x * axisN.x * a + cosTheta, axisN.y * axisN.x * a + axisN.z * sinTheta, axisN.z * axisN.x * a - axisN.y * sinTheta, axisN.x * axisN.y * a - axisN.z * sinTheta, axisN.y * axisN.y * a + cosTheta, axisN.z * axisN.y * a + axisN.x * sinTheta, axisN.x * axisN.z * a + axisN.y * sinTheta, axisN.y * axisN.z * a - axisN.x * sinTheta, axisN.z * axisN.z * a + cosTheta ); return mul(m, pos); } v2f vert (appdata v) { v2f o; v.vertex.xyz = rotate(v.vertex.xyz, _Axis.xyz, _Theta); o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); return col; } ENDCG } } }
今回は以上となります。 ここまでご視聴ありがとうございました。