夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

MRTK HandTrianglesShaderの中身を読み解く その⑪ ジオメトリシェーダーを読み解く Ⅸ Fly_B164()後半

本日はMRTK HandTrianglesShaderの調査枠です。

ジオメトリシェーダーを少しづつ読み解いています。

Fly_B164()ではパルスによるメッシュの回転を処理しています。

重要な関数なので前回と今回の二回に分けてみています。

〇Fly_B164()

void Fly_B164(
        float3 P0,
        float3 P1,
        float3 P2,
        float Transition,
        float Max_Hover,
        float Max_In_Angle,
        float Max_Out_Angle,
        float2 UV0,
        float2 UV1,
        float2 UV2,
        float2 PulseOrigin,
        float3 Nearest_P,
        bool Fading_Out,
        out float3 Q0,
        out float3 Q1,
        out float3 Q2    )
    {
        float3 N = normalize(cross(P1-P0,P2-P1));
        
        float k01 = dot(normalize((UV0+UV1)*0.5-PulseOrigin),normalize(UV1-UV0));
        float k12 = dot(normalize((UV1+UV2)*0.5-PulseOrigin),normalize(UV2-UV1));
        float k20 = dot(normalize((UV0+UV2)*0.5-PulseOrigin),normalize(UV2-UV0));
        
        float3 pulseDir = normalize( normalize(P1-P0)*k01+normalize(P2-P1)*k12 + normalize(P2-P0)*k20);
        float3 axis = normalize(cross(N,pulseDir));
        float3 center = Nearest_P; //(P0+P1+P2)/3.0;
        
        float angle, k;
        if (Fading_Out) {
            //float t = Transition<0.5 ? 2.0*(0.5-Transition)*(0.5-Transition) : 2.0*(0.5-Transition)*(0.5-Transition)+0.5;
            float t = smoothstep(0,1,Transition);
            angle = -Max_Out_Angle * (1.0-t);
            k = (1-t) * Max_Hover;
        } else {
            float t = smoothstep(0,1,Transition);
        //    float t = Transition*Transition;
            angle = Max_In_Angle * (1.0-t);
            k = (1-Transition) * Max_Hover;
        }
        
        float3 p0 = Rotate_Bid164(angle,center,axis,P0);
        float3 p1 = Rotate_Bid164(angle,center,axis,P1);
        float3 p2 = Rotate_Bid164(angle,center,axis,P2);
        
        if (false) {  ///(!Fading_Out) {
            float t = (Transition);
            p0 = Nearest_P + (p0-Nearest_P)*t;
            p1 = Nearest_P + (p1-Nearest_P)*t;
            p2 = Nearest_P + (p2-Nearest_P)*t;
        }
        
        Q0 = p0 + N * k;
        Q1 = p1 + N * k;
        Q2 = p2 + N * k;
        
        
    }

前回Fading_Outの真偽によって変わる条件分岐を見ました。

    if (false) {  ///(!Fading_Out) {
            float t = (Transition);
            p0 = Nearest_P + (p0-Nearest_P)*t;
            p1 = Nearest_P + (p1-Nearest_P)*t;
            p2 = Nearest_P + (p2-Nearest_P)*t;
        }

この部分はおそらくコメントアウトと同義です。

if文では真(True)の場合処理を実行するのでif(false)は絶対に処理を実行することはないはずなのでコメントアウトと同義と思われます。(違ったら教えて)

        float3 p0 = Rotate_Bid164(angle,center,axis,P0);
        float3 p1 = Rotate_Bid164(angle,center,axis,P1);
        float3 p2 = Rotate_Bid164(angle,center,axis,P2);

p0,p1,p2はそれぞれRotate_Bid164()に各頂点のベクトルを渡した返り値が入ります。

●Rotate_Bid164()
 float3 Rotate_Bid164(float A, float3 Center, float3 Axis, float3 XYZ)
    {
        float cosA = cos(A);
        float sinA = sin(A);
    
        float3 v = XYZ - Center;
    
        float ux = Axis.x;
        float uy = Axis.y;
        float uz = Axis.z;
    
        float r00 = cosA + ux*ux*(1-cosA);
        float r10 = uy*ux*(1-cosA)+uz*sinA;
        float r20 = uz*ux*(1-cosA)-uy*sinA;
        
        float r01 = ux*uy*(1-cosA)-uz*sinA;
        float r11 = cosA+uy*uy*(1-cosA);
        float r21 = uz*uy*(1-cosA)+ux*sinA;
    
        float r02 = ux*uz*(1-cosA)+uy*sinA;
        float r12 = uy*uz*(1-cosA)-ux*sinA;
        float r22 = cosA+uz*uz*(1-cosA);
    
        float rot_x = dot(v,float3(r00,r10,r20));
        float rot_y = dot(v,float3(r01,r11,r21));
        float rot_z = dot(v,float3(r02,r12,r22));
    
        return float3(rot_x,rot_y,rot_z) + Center;
    }

SinA、CosAにはSin(angle(Fading_Outの真偽によって値が変わる)),Cos(angle(Fading_Outの真偽によって値が変わる))が代入されます。

vには各頂点の位置ベクトルからメッシュの重心ベクトルを引いた値が入ります。(各成分ごとの重心と各頂点の距離)

ux,uy,uzにはAxisのx,y,z各成分が代入されます。(Axisにはメッシュの回転とパルスの方向のクロス積(外積)を正規化した値)

r00にはCos(angle)×Axisのx成分の二乗×(1-Cos(angle))が代入されます。

1-Cos(angle)は正矢といい画像の(Wikipedia様様)versinに当たるようです。

f:id:Holomoto-Sumire:20200520104856p:plain

r00,r10,r20,r01,r11,r12,r20,r21,r22はそれぞれメッシュの回転を行っています。0がx成分、1がy成分、2がz成分に当たります。

qiita.com

こちらの記事を参考にさせていただきました。

これによるとメッシュの回転処理を行っているようです。

それらをRotation()の返り値として返します。

メッシュの各頂点ごとにこれらの処理が行われそれぞれFly_B164()のP0,p1,p2に代入されます。

       Q0 = p0 + N * k;
        Q1 = p1 + N * k;
        Q2 = p2 + N * k;

Rotation()で処理をした各頂点ごとの回転の値にN(=メッシュの回転を方向)とk(1からTransitionを引いた値とMax_Hover(プロパティでのMax Hoverrの値 デフォルトで0.004)との積)が加算されたものがQ0,Q1,Q2に代入されています。

以上がFly()での処理になります。