【UE4】ObjectのRotationをMaterialから取得する方法 【★★☆】

※この記事で使用しているUnrealのVersionは04.23.0 Preview6です。

※この記事のサンプルプロジェクトは以下URLにアップされています。
サンプルプロジェクト

ObjectのRotationをMaterialから取得する 【★★☆】

UE4のMaterialには、座標変換系ノードの「Transform (Vector)」というノードがあります。

このノードは、つなげたベクトルを、任意の座標系から任意の座標系へと変換してくれるものです。

例えば頂点シェーダーで確かめてみましょう。

まず、超シンプルな頂点シェーダーを↓のように組んでみます。

これは、時間に応じてマテリアルを設定したオブジェクトが上下に動くというものです。

しかし、このオブジェクトを回転させても、World座標上でのZ軸での上下運動を行ってしまいます。

これを、オブジェクトの向きが変わっても、その向きで頂点シェーダーを行いたい場合には、「Transform(Vector)」ノードを使用します。

TransformノードのDetailは、「Source」部分に「Local Space」、「Destination」の部分に「World Space」を選択します。

そうすることで、オブジェクトが回転しても、自身の座標系に合わせて頂点シェーダーを展開してくれます。

ちなみに、 「Source」部分を「Tangent Space」 に設定すると、各頂点ごとの座標系での計算になるので、結果的にオブジェクトが大小しているのがわかる(Cubeだと、面が離れたりめり込んだりするが)

さて、座標系を変換してくれるノードがあるので、あとはそれを各軸の角度に変換してあげればいいだけです。

とりあえずこんな感じのマテリアルファンクションを組んでみました。

CustomNodeの中身

return InR < 0 ? 2 * pi - abs(InR) : InR;

Transformノードで回転行列を疑似的に再現し、そこから各軸の角度をAtanやAsinでだしています。

それらで出た値を、度数法に直したりしています(Degree)。

これにより、角度を数値として使用することができます。

↓Debug 3 Float Valuesで値を確認。

結果↓

小数点誤差は若干あるものの、オブジェクトの角度を取得することができました。

ちなみに、ワールド座標からローカル座標への変換行列をカスタムノードの「 GetPrimitiveData(Parameters.PrimitiveId.WorldToLocal (float3x3)」で取得することができます。
(詳しくはSceneData.ushをご確認ください)

これを利用して、変換行列から角度を求めることもできます。

カスタムノードの中身

float3x3 WtoL = GetPrimitiveData(Parameters.PrimitiveId).WorldToLocal;
float3 R = float3(
atan2(WtoL[2].y,WtoL[2].z) * -1.0,
asin(WtoL[2].x),
atan2(WtoL[1].x,WtoL[0].x)
);
return R < 0 ? 2 * pi - abs(R) : R;

以上

※この記事のサンプルプロジェクトは以下URLにアップされています。
サンプルプロジェクト