###unity_ObjectToWorldからスケール成分を取り出したい
#####参考にしました というかそのまま持ってきました [The Matrix and Quaternions FAQ](https://www.j3d.org/matrix_faq/matrfaq_latest.html) [OpenGLプログラミングメモ 行列:合成行列から拡大縮小成分を抜き出す](https://www21.atwiki.jp/opengl/pages/138.html)
Unity5.5からunity_Scaleの中身がfloat(1,1,1,1)になりました。 通常、それはそれで問題ありませんけど、それでもスケールの数値を所得したい! ということで、unity_ObjectToWorldに含まれているはずのスケール成分を抜き出してみました
変換行列の中身は大体こんな感じ
unityScale =
\begin{bmatrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & 1 & 0\\
0 & 0 & 0 & 1
\end{bmatrix}
\begin{matrix}
XScale成分(1,0,0),平行移動成分X\\
YScale成分(0,1,0),平行移動成分Y\\
ZScale成分(0,0,1),平行移動成分Z\\
0,0,0,1\\
\end{matrix}
さて参考にしたサイトのままですが、
変換行列の平行移動成分を除いて、各列3要素の
ベクトルの大きさを計算するとスケール成分が取り出せます。
\begin{vmatrix}
A
\end{vmatrix} = \sqrt{A{x}^2+A{y}^2+A{z}^2
}
これをScriptにするとこんな感じになります。
float sX = sqrt(unity_ObjectToWorld[0].x * unity_ObjectToWorld[0].x + unity_ObjectToWorld[0].y * unity_ObjectToWorld[0].y + unity_ObjectToWorld[0].z * unity_ObjectToWorld[0].z);
float sY = sqrt(unity_ObjectToWorld[1].x * unity_ObjectToWorld[1].x + unity_ObjectToWorld[1].y * unity_ObjectToWorld[1].y + unity_ObjectToWorld[1].z * unity_ObjectToWorld[1].z);
float sZ = sqrt(unity_ObjectToWorld[2].x * unity_ObjectToWorld[2].x + unity_ObjectToWorld[2].y * unity_ObjectToWorld[2].y + unity_ObjectToWorld[2].z * unity_ObjectToWorld[2].z);
検証用Shaderコードです。
Shader "Unlit/ScaleSample"
{
Properties{ }
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float mX = sqrt(unity_ObjectToWorld[0].x * unity_ObjectToWorld[0].x + unity_ObjectToWorld[0].y * unity_ObjectToWorld[0].y + unity_ObjectToWorld[0].z * unity_ObjectToWorld[0].z);
float mY = sqrt(unity_ObjectToWorld[1].x * unity_ObjectToWorld[1].x + unity_ObjectToWorld[1].y * unity_ObjectToWorld[1].y + unity_ObjectToWorld[1].z * unity_ObjectToWorld[1].z);
float mZ = sqrt(unity_ObjectToWorld[2].x * unity_ObjectToWorld[2].x + unity_ObjectToWorld[2].y * unity_ObjectToWorld[2].y + unity_ObjectToWorld[2].z * unity_ObjectToWorld[2].z);
float3 matrixDat = float3(mX, mY, mZ);
return float4(matrixDat, 1);
}
ENDCG
}
}
}
ということで実行結果です。 スケールを弄ると、色が変化しているのがわかりますね。
##以下メモ
#####平行移動行列
T =
\begin{bmatrix}
1 & 0 & 0 & X \\
0 & 1 & 0 & Y \\
0 & 0 & 1 & Z \\
0 & 0 & 0 & 1
\end{bmatrix}
#####スケール行列
S =
\begin{bmatrix}
x & 0 & 0 & 0 \\
0 & y & 0 & 0 \\
0 & 0 & z & 0 \\
0 & 0 & 0 & 1
\end{bmatrix}
#####回転行列
Rx =
\begin{bmatrix}
1 & 0 & 0 & 0\\
0 & cos\theta & -sin\theta & 0\\
0 & sin\theta & cos\theta & 0\\
0 & 0 & 0 & 1
\end{bmatrix}
Ry =
\begin{bmatrix}
cos\theta & 0 & sin\theta & 0 \\
0 & 1 & 0 & 0\\
-sin\theta & 0 & cos\theta & 0\\
0 & 0 & 0 & 1
\end{bmatrix}
Rz =
\begin{bmatrix}
cos\theta & -sin\theta & 0 & 0\\
sin\theta & cos\theta & 0 & 0\\
0 & 0 & 1 & 0\\
0 & 0 & 0 & 1
\end{bmatrix}
#####回転行列3軸
M = X・Y・Zと計算するとして展開するとこうなる
M =
\begin{bmatrix}
(cos\theta{y} * cos\theta{z}) & (-cos\theta{y} * -sin\theta{z}) & (-sin\theta{y}) & 0\\
(sin\theta{x} * sin\theta{y} * cos\theta{z} + cos\theta{x} * sin\theta{z}) & (-sin\theta{x} * sin\theta{y} * sin\theta{z} + cos\theta{x} * cos\theta{z}) & (-sin\theta{x} * cos\theta{y}) & 0\\
(-sin\theta{x} * sin\theta{y} * cos\theta{z} + sin\theta{x} * sin\theta{z}) & (cos\theta{x} * sin\theta{y} * sin\theta{z} + sin\theta{x} * cos\theta{z}) & (cos\theta{x} * cos\theta{y}) & 0\\
0 & 0 & 0 & 1
\end{bmatrix}