はじめに
Remote Assist やMicrosoft Meshでは、HoloLens 2で空間に線を描く機能があります。
このような機能を自分で実装したいと思ったので、やり方を調べてみました。
環境
Unity 2020.3.11f1
MRTK 2.7.2
OpenXR Plugin 2.1.8
どうやって実装する?
ポイントをまとめてみました。
空間に線を描くには?
UnityのTrail Rendererという機能を使います。
Trail Renderer - Unity マニュアル (unity3d.com)
これは移動するオブジェクトの軌跡を描画するものです。「Time」という軌跡の生存期間を指定するプロパティがあり、これを「Inifinity」にすると軌跡が残り続け、線を描いたようになります。
親指と人差し指でつまんでいるかを判断する
Trail Rendererのみだとずっと線を描くことになってしまい絵を描いたりや文字を書くことができません。そこで今回は「親指と人差し指をくっつけてつまんでいる」状態の時のみ線を描くようにしたいと思います。
つまんでいることをどのように判断するかは、親指と人差し指の距離によって判断することとします。
コードにすると以下のようになります。
//右手の親指と人差し指の位置情報の取得 if (HandJointUtils.TryGetJointPose(TrackedHandJoint.IndexTip, Handedness.Right, out MixedRealityPose indexPose) && HandJointUtils.TryGetJointPose(TrackedHandJoint.ThumbTip, Handedness.Right, out MixedRealityPose thumbPose)) { //親指と人差し指の距離を取得 float distance = Vector3.Distance(indexPose.Position, thumbPose.Position); //つまんでいるかの判断として、「親指と人差し指の距離が0.025よりも小さいとき」とする if (distance < 0.025) { //線を描く処理を書く } else { //つまんでいないときの処理を書く } } else { //指の位置の取得に失敗したときの処理を書く }
指の位置の取得方法については以前記事にしたものがあるのでそちらをご覧ください。
blog.jbs.co.jp
つまんでいるかを判断する距離を0.025にした理由は、色々と試した結果この数値がよさそうだったからです。
HoloLens 2で親指と人差し指をくっつけて距離を測定し続けたところ、だいたい0.015 - 0.02の間でした。0.02だとたまに「つまんでいるのに線が描けない」ということがあったため、0.025としました。
実装手順
プロジェクトの作成
Microsoft Learnの以下のモジュールを参考にプロジェクトを作成してください。
(「演習 - リソースをインポートして構成する」まででOKです)
Mixed Reality Toolkit の概要 - Mars キュリオシティ ローバーのホログラムを作成する - Learn | Microsoft Docs
スクリプトの作成
以下のようなスクリプトを作成します。
using Microsoft.MixedReality.Toolkit.Input; using Microsoft.MixedReality.Toolkit.Utilities; using UnityEngine; public class TrailTest : MonoBehaviour { public GameObject trailObject; GameObject currentLineObject = null; void Start() { //Trail Rendererの設定を行う var trailRenderer = trailObject.GetComponent<TrailRenderer>(); //軌跡の色を指定 trailRenderer.startColor = Color.red; trailRenderer.endColor = Color.red; //軌跡の太さを指定 trailRenderer.startWidth = 0.01f; trailRenderer.endWidth = 0.01f; //軌跡の残存時間を設定 //ここでは時間が経っても消えないようにしている trailRenderer.time = Mathf.Infinity; //軌跡の滑らかさを設定 値が小さいと線が滑らかになる trailRenderer.minVertexDistance = 0.01f; } void Update() { //右手の親指と人差し指の位置情報の取得 if (HandJointUtils.TryGetJointPose(TrackedHandJoint.IndexTip, Handedness.Right, out MixedRealityPose indexPose) && HandJointUtils.TryGetJointPose(TrackedHandJoint.ThumbTip, Handedness.Right, out MixedRealityPose thumbPose)) { //親指と人差し指の距離を取得 float distance = Vector3.Distance(indexPose.Position, thumbPose.Position); //つまんでいるかの判断として、「親指と人差し指の距離が0.025よりも小さいとき」とする if (distance < 0.025) { if (currentLineObject == null) { currentLineObject = Instantiate(trailObject); } //線を描くためのオブジェクトを人差し指の位置に設定する currentLineObject.transform.position = indexPose.Position; currentLineObject.transform.rotation = indexPose.Rotation; } else { //つまんでいないと判断したら線を描かないようにする if (currentLineObject != null) { currentLineObject = null; } } } else { Debug.Log("Failed"); } } }
Unityエディタでの設定
① Inspectorで右クリック→「Create Empty」を選択して、空のオブジェクトを作成します。名前は「DrawObject」としました。
②「Add Component」ボタンから「Trail Renderer」を追加します。
③ Trail Rendererの中に「Material」という項目があり、この中のElement 0には「Sprite-Default」を選択します。
④ Inspectorで右クリック→「Create Empty」を選択して、空のオブジェクトを作成します。名前は「DrawManager」としました。
⑤ 作成したスクリプトを「DrawManager」に追加します。
⑥ スクリプトの項目「Trail Object」には①で作成した「DrawObject」を挿入します。
以上で設定は完了です。
デモ動画
HoloLens 2にデプロイすると以下のように動作します。
参考リンク
【OculusHandTracking】LineRendererでお絵かき【Unity】 - トマシープが学ぶ (hatenablog.com)