夜風のMixedReality

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

MapSDK for Untiyを学ぶ 音声でマップをズームする 準備

本日はMap-SDKの調査枠です。

Microsoft Map-SDK for Unityとは?

Microsoft Map-SDK for Unity(Map-SDK)はMicrosoftが提供しているBing Mapの情報をHoloLensをはじめとするMixedRealityデバイスで使用できるツールです。

これを使用することで自身のアプリに簡単に地図を実装することができます。

また,Map-SDKの特徴として地形や場所によっては建物などを立体的に表示、見ることができます。

f:id:Holomoto-Sumire:20201005090936j:plain

Map-SDKの導入に関してはこちらの記事を参考にしてください

redhologerbera.hatenablog.com

〇音声を使用して地図をズームする

今回は音声認識を使用して地図をズームをできるようにします。

まず、地図上の度の座標でズームを行うのかを設定します。

今回は日本の47都道府県を音声で移動できるようにします。

〇MapPinの設定

①Map-SDKの導入が完了しているシーンで[MapRenderer]コンポーネントがアタッチされているオブジェクト(Mapオブジェクト)に[Map PinLayer]コンポーネント、[Map Pin Provider]コンポーネントをアタッチしします。

f:id:Holomoto-Sumire:20201031191142j:plain

・[Map Pin Provider]コンポーネントの[Map PinLayer]には自身の[Map PinLayer]コンポーネント、[Map Pin Prefab]にはExamplesで提供されている[SmallMapPin]プレファブを設定します。

エクスプローラーからUnityのプロジェクトがあるフォルダを開き、Assets内で右クリック、[新規作成]からテキストファイルを作成します。

f:id:Holomoto-Sumire:20201031192058j:plain

③作成したテキストファイルの拡張子を[.csv]に変更します。(ここではファイルの名前を47都道府県を意味する[47state]と名付けています。)

f:id:Holomoto-Sumire:20201031192344j:plain

 これが47都道府県の場所にピンを表示するデータになります。

④作成したcsvファイルの中にデータを書き込みます。

今回データは以下のサイトを参考にさせていただきました。

www.benricho.org

43.06417,141.34694,Hokkaido,0
40.82444,140.74,Aomori,0
39.70361,141.1525,Iwate,0
38.26889,140.87194,Miyagi,0
39.71861,140.1025,Akita,0
38.24056,140.36333,Yamagata,0
37.75,140.46778,Fukushima,0
36.34139,140.44667,Ibaragi,0
36.56583,139.88361,Tichigi,0
36.39111,139.06083,Gunma,0
35.85694,139.64889,Saitama,0
35.60472,140.12333,Chiba,0
35.68944,139.69167,Tokyo,0
35.44778,139.6425,Kanagawa,0
37.90222,139.02361,Nigata,0
36.69528,137.21139,Toyama,0
36.59444,136.62556,Ishikawa,0
36.06528,136.22194,Fukui,0
35.66389,138.56833,Yamanashi,0
36.65139,138.18111,Nagano,0
35.39111,136.72222,Gifu,0
34.97694,138.38306,Shizuoka,0
35.18028,136.90667,Aichi,0
34.73028,136.50861,Mie,0
35.00444,135.86833,Shiga,0
35.02139,135.75556,Kyoto,0
34.68639,135.52,Osaka,0
34.69139,135.18306,Hyogo,0
34.68528,135.83278,Nara,0
34.22611,135.1675,Wakayama,0
35.50361,134.23833,Tottori,0
35.47222,133.05056,Shimane,0
34.66167,133.935,Okayama,0
34.39639,132.45944,Hirosima,0
34.18583,131.47139,Yamaguchi,0
34.06583,134.55944,Tokushima,0
34.34028,134.04333,Kagawa,0
33.84167,132.76611,Ehime,0
33.55972,133.53111,Kouchi,0
33.60639,130.41806,Fukuoka,0
33.24944,130.29889,Saga,0
32.74472,129.87361,Nagasaki,0
32.78972,130.74167,Kumamoto,0
33.23806,131.6125,Oita,0
31.91111,131.42389,Miyazaki,0
31.56028,130.55806,Kagoshima,0
26.2125,127.68111,Okinawa,0

⑤作成したデータを[Map Pin Provider]コンポーネントの[Map Pin Location csv]にアタッチします。

f:id:Holomoto-Sumire:20201031194113j:plain

この状態でUnity上で一度実行します。

f:id:Holomoto-Sumire:20201031194318j:plain

(ピン同士が重なって見えにくいですが)各都道府県の位置にピン止めが行われました。

以上で準備が完了しました。

本日はここまでで明日以降音声の機能を実装します。

Elastic System Examples ~MixedRealityToolkitExamplesを触ってみる。 その③ Transration Elastic

本日はMRTK Examples調査枠です。

前回に引き続き[Elastic System Examples]を調査していきます。

[Elastic System Examples]はばねのような弾性物体の物理シュミュレーションを見ることができます。

前回まででElastic Systemを機能させている[Elastic Manager]コンポーネントを調査しました。

〇Basic ObjectManipulator Integration

f:id:Holomoto-Sumire:20201030091058j:plain

〇VolumeElasticSystem

このオブジェクトではボリューム弾性(位置による弾性)が設定されています。

カップをつかんで移動することにより元の場所に戻ろうとする力が働いています。

f:id:Holomoto-Sumire:20201027190229g:plain

[Elastic Manager]コンポーネントでは[Manipulation types using elastic]の設定が[Move]に設定されています。

f:id:Holomoto-Sumire:20201030094605j:plain

これによって弾性シュミュレーションがMove(移動)で働く設定になります。

〇QuaternionElasticSystem

このマグカップにはクォータニオンのバネが付いていて、元の角度に回転にするような力が働くように設定されています。

ボリューム弾性のカップとは違い位置を移動することはできません。

代わりに傾きを与えることで元の傾きに戻ろうとするように働きます。

f:id:Holomoto-Sumire:20201030093653g:plain

[Elastic Manager]コンポーネントでは[Manipulation types using elastic]の設定が[Rotate]に設定されています。

f:id:Holomoto-Sumire:20201030095143j:plain

[Move]では[Transration Elastic Extent]という設定項目が表示されますが[Rotate]では[Rotation Elastic Extent]というどこまで回転させたらどれだけの力がかかるかが設定できます。

f:id:Holomoto-Sumire:20201030095422j:plain

〇Combined

このマグカップは、クォータニオン弾性システムとボリューム弾性システムの両方が設定されています。

f:id:Holomoto-Sumire:20201030094350g:plain

[Elastic Manager]コンポーネントでは[Manipulation types using elastic]では[Mixed]となっており[Move]、[Rotate]が設定されています。

f:id:Holomoto-Sumire:20201030095746j:plain

こちらでは[Transration Elastic Extent],[Rotation Elastic Extent]どちらも表示されており、それぞれの設定を行うことで移動、回転どちらの物理シュミュレーションも設定することができます。

f:id:Holomoto-Sumire:20201030100026j:plain

また、オブジェクトを移動させるために使用する[ObjectManipulator]では[Elastic System]の項目があり[Elastic Manager]コンポーネントと併用することで、弾性システムの任意の組み合わせと設定を同時に行うことができます。

f:id:Holomoto-Sumire:20201030094323j:plain

HoloLens 2実機でHandMenuが表示されない問題の解消 

本日はHoloLens 2のHandMenuに関するトラブルシューティングになります。

〇HandMenuとは?

f:id:Holomoto-Sumire:20200908093228g:plain

手に沿って追随するUIです。

ユーザーがどのような位置や状況にあってもユーザー自身の手を基準に現れるため非常に使いやすいUIです。

〇発生している問題

HandMenuを使用しているプロジェクト(ここではMixedRealityToolkit Example HandMenuExamplesを使用)ARM64でデプロイした場合HoloLens 2実機でHandMenuが表示されない or 最初の一度のみ表示される。

どちらの場合もEditor上では正常にHandMenuが機能していますが実機で動かなくなります。

f:id:Holomoto-Sumire:20201029091556j:plain

https://youtu.be/zxdL4HVtrh4

〇発生環境

・Unity2019.3.9f1

・MRTK v2.5

・VisualStudio2019(16.7.7)

〇原因

 VisualStudio側にバグがあり

 こちらの問題はすでにイシューが上がっており、VisualStudio2019の次期更新(16.8)で解消されるようです。

f:id:Holomoto-Sumire:20201029090741j:plain
MRTKのリリースページより

github.com

 これによるとSolver.UpdateWorkingScaleToGoalまたはUpdateWorkingPositionToGoalのコードを生成する際にIL2CPPでのコンパイルのバグが発生しているようです。

 これによって手の検知がうまくできなくなっているようです。

〇解消法

この問題の解消法はいくつか存在します。

①ARM64ではなくARMでデプロイする

 ARM64でデプロイ時にバグがあるためARMに変更することで正常に機能します。

f:id:Holomoto-Sumire:20201029091359j:plain

②HandMenuの設定を変える。

HandMenuを行っている[HandConstraintPalmUp]コンポーネントの[Smmothing]のチェックボックスを無効化(デフォルトでは有効)することでこの問題が解消します。

f:id:Holomoto-Sumire:20201029091052j:plain

Elastic System Examples ~MixedRealityToolkitExamplesを触ってみる。 その② Transration Elastic

本日はMRTKのサンプルの調査枠です。

昨日に引き続き[Elastic System Examples]を見ていきます。

〇Elastic System Examplesとは?

MRTKでばねのような動きや弾性を行う物理シュミュレーションを提供するサンプルです。

昨日の記事では[Elastic System Examples]のシーン構造とElastic Systemを機能している[Elastic Manager]コンポーネントの[Transration Elastic]のパラメータを見ていきました。

redhologerbera.hatenablog.com

本日は[Transration Elastic Extent]を見ていきます。

・Tansration Elastic Extent

f:id:Holomoto-Sumire:20201028110417j:plain

・Stretch Bounds(伸縮境界線)

[Center],[Extent]とそれぞれベクトルとしてのパラメータが用意されています。

f:id:Holomoto-Sumire:20201028111702j:plain

[Center]はBoundsの中心点、[Extent]は範囲を設定します。

f:id:Holomoto-Sumire:20201027190229g:plain
Center,Extent=0,0,0

f:id:Holomoto-Sumire:20201028220732g:plain
Extent =1,1,1

・Use Bounds

f:id:Holomoto-Sumire:20201028111725j:plain

設定されている[Bounds]を使用するかどうかの設定です。

[Bounds]はこの設定にチェックを入れていないと使用することはできません。

・SnapPoints

f:id:Holomoto-Sumire:20201028111746j:plain

システムがスナップを検知する範囲内のポイント数と位置を指定します。。

f:id:Holomoto-Sumire:20201028222130g:plain
Snap Point = 0,0,0  

0にすることで触った瞬間スプリングが作動します。

・Repeat Snap Points

[SnapPoint]を繰り返すかどうか?を指定します。

f:id:Holomoto-Sumire:20201028111812j:plain

・Snap Radius

f:id:Holomoto-Sumire:20201028111828j:plain

スプリングを強制的に開始する距離に当たります。

以上でElastic Managerコンポーネントのざっくりとした理解ができました。 次からはサンプル内でどのような表現ができるかを学んでいきます。

Elastic System Examples ~MixedRealityToolkitExamplesを触ってみる。 その① Transration Elastic

本日はMRTKのExamplesシーンの勉強枠です。

Elastic System Examplesを調査していきます。

〇Elastic Systemとは?

Elasticとは弾性、伸縮性を意味します。

このサンプルではHoloLensのMixedReality体験の中で弾性の物理シュミュレーションを体験することができます。

〇シーン構成

シーンではDiscriptionPanelのほか3つのフィールド分かれてオブジェクトが配置されています。

f:id:Holomoto-Sumire:20201027182823j:plain

〇Discription

f:id:Holomoto-Sumire:20201027183150j:plain

ほかのサンプルシーン同様このシーンの概要、できることに関して説明がされています。

ElasticSystemはMRTKでのダイナミックで応答性の高いフィードバックとアニメーションを可能にしており、出力は、シェーダー、マテリアル、トランスフォームなどさまざまな形で使用できるようです。

ElasticSystemは、次の2つの構成情報によって駆動されます。

①エクステント情報

 定義した最小/最大のエンドポイントとスナップ間隔/ポイントを設定することができます。

②弾性スプリング

 その物体の質量、張力定数、エンドスナップスプリング定数、スナップ間隔スプリング定数、ドラッグ/ダンピング係数、スナップポイント半径などを設定できます。

二つの設定を組み合わせることで物理シュミュレーションを行うようです。

〇Basic ObjectManipulator Integration(基本的なオブジェクトマニュピュレーターの統合)

今回は[Basic ObjectManipulator integration]を調査します。

f:id:Holomoto-Sumire:20201027185013j:plain

[Basic ObjectManipulator integration]には3つのコーヒーカップオブジェクトが配置されており、それぞれ違う設定となっています。

それぞれを見ていきます。

〇VolumeElasticSystem(体積弾性体)

f:id:Holomoto-Sumire:20201027190229g:plain

このマグカップには立体的なバネのような設定がされており、元の位置にはねながら戻るようなっています。

これはカップオブジェクトにアタッチされた[Elastic Manager]コンポーネントによって機能しています。

f:id:Holomoto-Sumire:20201027190802j:plain

[Elastic Manager]コンポーネントにはどのように動作するのか?[Transration Elastic]、[Transration Elastic Extent]の設定項目があります。

[Transration Elastic]の設定項目には[Transration Elastic Configuration]がアタッチされており、質量、手の定数、終了定数、スナップ定数が設定できます。

f:id:Holomoto-Sumire:20201027191452j:plain

・Mass K

この値を上げることでばねの振幅が大きくゆっくりとなります。 また筆者環境では若干fpsが落ちました。

f:id:Holomoto-Sumire:20201027190229g:plain
Mass=0.01

f:id:Holomoto-Sumire:20201027192102g:plain
Mass=1

・Hand K

この値は手の感度に当たるようです。 0にするとつかめないようになります。

f:id:Holomoto-Sumire:20201027190229g:plain
Hand k=3

f:id:Holomoto-Sumire:20201027192433g:plain
Hand K=0

・End K

この値を下げることで手を離す前に物理挙動が始まります。

f:id:Holomoto-Sumire:20201027190229g:plain
End K =4

f:id:Holomoto-Sumire:20201027192757g:plain
End K=0

・Snap K

この値は元の場所に戻ろうとする力を指します。

f:id:Holomoto-Sumire:20201027190229g:plain
Snap K =2

f:id:Holomoto-Sumire:20201027193210g:plain
Snap K =0

・Drag

この値はばねの抵抗を示します。

f:id:Holomoto-Sumire:20201027190229g:plain
Drag =0.1

f:id:Holomoto-Sumire:20201027193634g:plain
Drag=1

以上がTransration Elasticの設定項目です。

次回以降続きを見ていきます。

MRTK StanderdShaderを読み解く その17 RoundCorners

本日はMRTKシェーダー枠です。

今回はRoundCornerを読み解きます。

〇RoundCorner

[RoundCorner]は一言で表すとメッシュのエッジを落とすシェーダーの機能です。

[RoundCorner]の機能を用いることで正方形の板のオブジェクトを円の見た目に変えることなどできます。

f:id:Holomoto-Sumire:20201026090235g:plain

〇フラグメントシェーダー

RoundCornerはピクセル色の描画に当たるフラグメントシェーダーで処理されます。

    #if defined(_ROUND_CORNERS)
                    float2 halfScale = i.scale.xy * 0.5;
                    float2 roundCornerPosition = distanceToEdge * halfScale;
                    fixed currentCornerRadius; 
                    currentCornerRadius = _RoundCornerRadius;
                    float cornerCircleRadius = saturate(max(currentCornerRadius - _RoundCornerMargin, 0.01)) * i.scale.z;
                    float2 cornerCircleDistance = halfScale - (_RoundCornerMargin * i.scale.z) - cornerCircleRadius;
                    float roundCornerClip = RoundCorners(roundCornerPosition, cornerCircleDistance, cornerCircleRadius);
    #endif

RoundCornerを使用するためにRoundCorner用の各変数を作成します。

halfScaleはv2f構造体のscale=TEXCOORD3(テクスチャ画像)の半分となった値が入ります。

roundCornerPositionには直前で定義されたdistanceToEdgeにhalfScaleが積算されています。

 #if defined(_DISTANCE_TO_EDGE)
                    fixed2 distanceToEdge;
                    distanceToEdge.x = abs(i.uv.x - 0.5) * 2.0;
                    distanceToEdge.y = abs(i.uv.y - 0.5) * 2.0;
    #endif

distanceToEdgeはV2fのuv(テクスチャ座標)の各成分から0.5を引いた絶対値を倍にしています。 

currentCornerRadiusはマテリアル側で設定される_RoundCornerRadius(0~0.5)がそのまま代入されます。

この_RoundCornerRadiusはMixedRealityStandardShaderGUIによって[Unit Radius]として表示されます。

f:id:Holomoto-Sumire:20201026092455j:plain

cornerCircleRadiusはcurrentCornerRadiusからMaterialで設定できる_RoundCornerMarginの値を引いた値が0.01より大きければその値、小さければ0.01が1までの値の間に収めた値にv2f構造体のscaleのz成分が積算されます。

currentCornerRadiusはRoundCornerRadiusなのでRoundCornerRadiusと_RoundCornerMarginの差になります。

cornerCircleDistanceにはhalfScaleの値から_RoundCornerMarginにv2f構造体のscale.zを積算した値にcornerCircleRadiusを引いた値が代入されます。

roundCornerClipには RoundCorners(roundCornerPosition, cornerCircleDistance, cornerCircleRadius)が代入されます。

このRoundCorners()は次のようになっています。

  inline fixed RoundCorners(float2 position, float2 cornerCircleDistance, float cornerCircleRadius)
                {
                    return (PointVsRoundedBox(position, cornerCircleDistance, cornerCircleRadius) < 0.0);
                }
               inline float PointVsRoundedBox(float2 position, float2 cornerCircleDistance, float cornerCircleRadius)
                {
                    return length(max(abs(position) - cornerCircleDistance, 0.0)) - cornerCircleRadius;
                }

PointVsRoundedBoxの返り値はroundCornerPositionの絶対値からcornerCircleDistanceを引いた値の正の値からcornerCircleRadiusを引いた値が返されます。これがroundCornerClipつまりクリッピングされる値になります。

 #if defined(_ROUND_CORNERS)
                    albedo *= roundCornerClip;
                    pointToLight *= roundCornerClip;
    #endif

    #if defined(_ALPHA_CLIP)
   
                    clip(albedo.a - _Cutoff);
                    albedo.a = 1.0;
    #endif

albedoの値にこのroundCornerClipが積算されこれがRoundCornerの値を最終的な連でリング結果に反映させる処理になります。

以上でRoundCornerでした。 今回はざっくりと呼んでいたのでまた改めてじっくり読み解きます。

〇shader

今回作成したシェーダーは次の通りです。

Shader "Custom/MRTKRoundCorner"
{
    Properties
    {
        // Main maps.
        _Color("Color", Color) = (1.0, 1.0, 1.0, 1.0)
        _MainTex("Albedo", 2D) = "white" {}

        _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
   

            // Rendering options.
            [Toggle(_DIRECTIONAL_LIGHT)] _DirectionalLight("Directional Light", Float) = 1.0
            
        

            // Fluent options.
         
            [Toggle(_ROUND_CORNERS)] _RoundCorners("Round Corners", Float) = 0.0
            _RoundCornerRadius("Round Corner Radius", Range(0.0, 0.5)) = 0.25
            _RoundCornerMargin("Round Corner Margin", Range(0.0, 0.5)) = 0.01
          
                // Advanced options.
                [Enum(RenderingMode)] _Mode("Rendering Mode", Float) = 0                                     // "Opaque"
                [Enum(CustomRenderingMode)] _CustomMode("Mode", Float) = 0                                   // "Opaque"
                [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Source Blend", Float) = 1                 // "One"
                [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Destination Blend", Float) = 0            // "Zero"
                [Enum(UnityEngine.Rendering.BlendOp)] _BlendOp("Blend Operation", Float) = 0                 // "Add"
                [Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("Depth Test", Float) = 4                // "LessEqual"
                [Enum(DepthWrite)] _ZWrite("Depth Write", Float) = 1                                         // "On"
                _ZOffsetFactor("Depth Offset Factor", Float) = 0                                             // "Zero"
                _ZOffsetUnits("Depth Offset Units", Float) = 0                                               // "Zero"
                [Enum(UnityEngine.Rendering.ColorWriteMask)] _ColorWriteMask("Color Write Mask", Float) = 15 // "All"
                [Enum(UnityEngine.Rendering.CullMode)] _CullMode("Cull Mode", Float) = 2                     // "Back"
                _RenderQueueOverride("Render Queue Override", Range(-1.0, 5000)) = -1
                [Toggle(_INSTANCED_COLOR)] _InstancedColor("Instanced Color", Float) = 0.0
                [Toggle(_IGNORE_Z_SCALE)] _IgnoreZScale("Ignore Z Scale", Float) = 0.0
                [Toggle(_STENCIL)] _Stencil("Enable Stencil Testing", Float) = 0.0
                _StencilReference("Stencil Reference", Range(0, 255)) = 0
                [Enum(UnityEngine.Rendering.CompareFunction)]_StencilComparison("Stencil Comparison", Int) = 0
                [Enum(UnityEngine.Rendering.StencilOp)]_StencilOperation("Stencil Operation", Int) = 0
    }

        SubShader
            {
                Pass
                {
                    Name "Main"
                    Tags{ "RenderType" = "Opaque" "LightMode" = "ForwardBase" }

                    Blend[_SrcBlend][_DstBlend]
                    BlendOp[_BlendOp]

                    CGPROGRAM
                    #pragma vertex vert
                    #pragma fragment frag

                    #pragma shader_feature _DIRECTIONAL_LIGHT
                    #pragma shader_feature _ROUND_CORNERS       
                    #include "UnityCG.cginc"
                    #include "UnityStandardConfig.cginc"
                    #include "UnityStandardUtils.cginc"
                    #include "MixedRealityShaderUtils.cginc"

                // This define will get commented in by the UpgradeShaderForLightweightRenderPipeline method.
                //#define _LIGHTWEIGHT_RENDER_PIPELINE

    #if  defined(_DIRECTIONAL_LIGHT)
                #define _NORMAL
    #else
                #undef _NORMAL
    #endif

    #if defined(_NORMAL) || defined(_PROXIMITY_LIGHT)
                #define _WORLD_POSITION
    #else
                #undef _WORLD_POSITION
    #endif

    #if  defined(_ROUND_CORNERS)
                #define _ALPHA_CLIP
    #else
                #undef _ALPHA_CLIP
    #endif

    #if  defined(_ROUND_CORNERS) 
                #define _SCALE
    #else
                #undef _SCALE
    #endif

    #if defined(_DIRECTIONAL_LIGHT) 
                #define _FRESNEL
    #else
                #undef _FRESNEL
    #endif

    #if defined(_ROUND_CORNERS) 
                #define _DISTANCE_TO_EDGE
    #else
                #undef _DISTANCE_TO_EDGE
    #endif

    #if !defined(_DISABLE_ALBEDO_MAP)  
                #define _UV
    #else
                #undef _UV
    #endif

                struct appdata_t
                {
                    float4 vertex : POSITION;
                    // The default UV channel used for texturing.
                    float2 uv : TEXCOORD0;
  
                    // Used for smooth normal data (or UGUI scaling data).
                    float4 uv2 : TEXCOORD2;
                    // Used for UGUI scaling data.
                    float2 uv3 : TEXCOORD3;
 
                    fixed3 normal : NORMAL;
  
                    UNITY_VERTEX_INPUT_INSTANCE_ID
                };

                struct v2f
                {
                    float4 position : SV_POSITION;
   
    #if defined(_UV)
                    float2 uv : TEXCOORD0;
    #endif
   

    #if defined(_WORLD_POSITION)
    
                    float3 worldPosition : TEXCOORD2;
    #endif
    #if defined(_SCALE)
                    float3 scale : TEXCOORD3;
    #endif
    #if defined(_NORMAL)
                    fixed3 worldNormal : COLOR3;
    #endif
                    UNITY_VERTEX_OUTPUT_STEREO
                };

  
                fixed4 _Color;

                sampler2D _MainTex;
                fixed4 _MainTex_ST;

    #if defined(_ALPHA_CLIP)
                fixed _Cutoff;
    #endif
                fixed _Metallic;
                fixed _Smoothness;
    #if defined(_DIRECTIONAL_LIGHT)
  
                fixed4 _LightColor0;
    #endif

    #if defined(_REFRACTION)
                fixed _RefractiveIndex;
    #endif
 
      #if defined(_ROUND_CORNERS)
                fixed _RoundCornerRadius;
                fixed _RoundCornerMargin;
    #endif

    #if defined(_ROUND_CORNERS) 
                fixed _EdgeSmoothingValue;
    #endif

    #if defined(_DIRECTIONAL_LIGHT)
                static const fixed _MinMetallicLightContribution = 0.7;
                static const fixed _IblContribution = 0.1;
    #endif


    #if defined(_FRESNEL)
                static const float _FresnelPower = 8.0;
    #endif


    #if defined(_ROUND_CORNERS)
                inline float PointVsRoundedBox(float2 position, float2 cornerCircleDistance, float cornerCircleRadius)
                {
                    return length(max(abs(position) - cornerCircleDistance, 0.0)) - cornerCircleRadius;
                }

                inline fixed RoundCornersSmooth(float2 position, float2 cornerCircleDistance, float cornerCircleRadius)
                {
                    return smoothstep(1.0, 0.0, PointVsRoundedBox(position, cornerCircleDistance, cornerCircleRadius) / _EdgeSmoothingValue);
                }

                inline fixed RoundCorners(float2 position, float2 cornerCircleDistance, float cornerCircleRadius)
                {
  
                    return (PointVsRoundedBox(position, cornerCircleDistance, cornerCircleRadius) < 0.0);

                }
    #endif


                v2f vert(appdata_t v)
                {
                    v2f o;
                    UNITY_SETUP_INSTANCE_ID(v);
                    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                    float4 vertexPosition = v.vertex;

    #if defined(_WORLD_POSITION) 
                    float3 worldVertexPosition = mul(unity_ObjectToWorld, vertexPosition).xyz;
    #endif

    #if defined(_SCALE)
                    o.scale.x = length(mul(unity_ObjectToWorld, float4(1.0, 0.0, 0.0, 0.0)));
                    o.scale.y = length(mul(unity_ObjectToWorld, float4(0.0, 1.0, 0.0, 0.0)));
         o.scale.z = length(mul(unity_ObjectToWorld, float4(0.0, 0.0, 1.0, 0.0)));

   
    #endif

                    fixed3 localNormal = v.normal;

    #if defined(_NORMAL) 
                    fixed3 worldNormal = UnityObjectToWorldNormal(localNormal);
    #endif


                    o.position = UnityObjectToClipPos(vertexPosition);

    #if defined(_WORLD_POSITION)
                    o.worldPosition.xyz = worldVertexPosition;
    #endif


    #if  defined(_ROUND_CORNERS)
                    o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);

                    float minScale = min(min(o.scale.x, o.scale.y), o.scale.z);

                    if (abs(localNormal.x) == 1.0) // Y,Z plane.
                    {
                        o.scale.x = o.scale.z;
                        o.scale.y = o.scale.y;

                    }
                    else if (abs(localNormal.y) == 1.0) // X,Z plane.
                    {
                        o.scale.x = o.scale.x;
                        o.scale.y = o.scale.z;

  
                    }
                    else  // X,Y plane.
                    {
                        o.scale.x = o.scale.x;
                        o.scale.y = o.scale.y;

  
                    }

                    o.scale.z = minScale;

   
    #elif defined(_UV)
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    #endif

    #if defined(_NORMAL)
  
    #if defined(_NORMAL_MAP)
                    fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
                    fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w;
                    fixed3 worldBitangent = cross(worldNormal, worldTangent) * tangentSign;
                    o.tangentX = fixed3(worldTangent.x, worldBitangent.x, worldNormal.x);
                    o.tangentY = fixed3(worldTangent.y, worldBitangent.y, worldNormal.y);
                    o.tangentZ = fixed3(worldTangent.z, worldBitangent.z, worldNormal.z);
    #else
                    o.worldNormal = worldNormal;
    #endif
    #endif

                    return o;
                }

                fixed4 frag(v2f i, fixed facing : VFACE) : SV_Target
                {
 



  
                    fixed4 albedo = tex2D(_MainTex, i.uv);
    #if defined(_DISTANCE_TO_EDGE)
                    fixed2 distanceToEdge;
                    distanceToEdge.x = abs(i.uv.x - 0.5) * 2.0;
                    distanceToEdge.y = abs(i.uv.y - 0.5) * 2.0;
    #endif

                    // Rounded corner clipping.
    #if defined(_ROUND_CORNERS)
                    float2 halfScale = i.scale.xy * 0.5;
                    float2 roundCornerPosition = distanceToEdge * halfScale;

                    fixed currentCornerRadius;

 
                    currentCornerRadius = _RoundCornerRadius;


                    float cornerCircleRadius = saturate(max(currentCornerRadius - _RoundCornerMargin, 0.01)) * i.scale.z;

                    float2 cornerCircleDistance = halfScale - (_RoundCornerMargin * i.scale.z) - cornerCircleRadius;

                    float roundCornerClip = RoundCorners(roundCornerPosition, cornerCircleDistance, cornerCircleRadius);
    #endif

   
                    albedo *= _Color;
   
                    // Normal calculation.
    #if defined(_NORMAL)
                    fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPosition.xyz));
  
                    fixed3 worldNormal;

    #if defined(_NORMAL_MAP)
 
                    fixed3 tangentNormal = UnpackScaleNormal(tex2D(_NormalMap, i.uv), _NormalMapScale);
                    worldNormal.x = dot(i.tangentX, tangentNormal);
                    worldNormal.y = dot(i.tangentY, tangentNormal);
                    worldNormal.z = dot(i.tangentZ, tangentNormal);
                    worldNormal = normalize(worldNormal) * facing;

    #else
                    worldNormal = normalize(i.worldNormal) * facing;
    #endif
    #endif

                    fixed pointToLight = 1.0;
                    fixed3 fluentLightColor = fixed3(0.0, 0.0, 0.0);


    #if defined(_ROUND_CORNERS)
                    albedo *= roundCornerClip;
                    pointToLight *= roundCornerClip;
    #endif

    #if defined(_ALPHA_CLIP)
   
                    clip(albedo.a - _Cutoff);
                    albedo.a = 1.0;
    #endif

                    // Blinn phong lighting.
    #if defined(_DIRECTIONAL_LIGHT)
   
                    float4 directionalLightDirection = _WorldSpaceLightPos0;
                    fixed diffuse = max(0.0, dot(worldNormal, directionalLightDirection));
                    fixed specular = 0.0;
    #endif

                    // Image based lighting (attempt to mimic the Standard shader).
   
                    fixed3 ibl = unity_IndirectSpecColor.rgb;
   
                    // Fresnel lighting.
    #if defined(_FRESNEL)
                    fixed fresnel = 1.0 - saturate(abs(dot(worldViewDir, worldNormal)));
  
                    fixed3 fresnelColor = unity_IndirectSpecColor.rgb * (pow(fresnel, _FresnelPower) * max(_Smoothness, 0.5));
    #endif
                    // Final lighting mix.
                    fixed4 output = albedo;
  
                    fixed3 ambient = glstate_lightmodel_ambient + fixed3(0.25, 0.25, 0.25);

                    fixed minProperty = min(_Smoothness, _Metallic);
    #if defined(_DIRECTIONAL_LIGHT)
                    fixed oneMinusMetallic = (1.0 - _Metallic);
                    output.rgb = lerp(output.rgb, ibl, minProperty);
 
                    fixed3 directionalLightColor = _LightColor0.rgb;

                    output.rgb *= lerp((ambient + directionalLightColor * diffuse + directionalLightColor * specular) * max(oneMinusMetallic, _MinMetallicLightContribution), albedo, minProperty);
                    output.rgb += (directionalLightColor * albedo * specular) + (directionalLightColor * specular * _Smoothness);
                    output.rgb += ibl * oneMinusMetallic * _IblContribution;

    #endif

    #if defined(_FRESNEL)
                    output.rgb += fresnelColor * (1.0 - minProperty);   
    #endif
                    return output;
                }
                ENDCG
            }
            }
               Fallback "Hidden/InternalErrorShader"
                      
}

JoystickExample ~MixedRealityToolkitExamplesを触ってみる~ その③ Joystickを利用する

本日はMixedRealityToolkitExamplesの調査枠です。

昨日オリジナルのJoystickを作成しました。

redhologerbera.hatenablog.com

本日はこちらをHoloLens 2実機で使用していきます。

〇ターゲットの追加

スティックの動作に対応するオブジェクトを追加します。

①シーンにCubeを追加します。位置をx,y,z=0,0.3,0.5、スケールを0.5,0.5,0.5に設定します。

f:id:Holomoto-Sumire:20201025182455j:plain

②[JoysticClassicPrefab]の[JoystickController]コンポーネントの[TargetObject]に作成したCubeをアタッチします。

f:id:Holomoto-Sumire:20201025182651j:plain

③[JoystickController]コンポーネントを画像のように設定します。

f:id:Holomoto-Sumire:20201025183630j:plain

〇実機で確認

オブジェクトを設定したので実機で確認します。

youtu.be

以上でオリジナルの設定でJoystickを使用することができました。