5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Meta QuestのMRモードで掃除した場所を可視化する方法

Posted at

はじめに

クイックルワイパーで部屋を掃除する際、どこが既にきれい/汚いのか分からなくて効率が悪いなと普段から思っていました。
そこで、Meta QuestのMRモードで掃除した場所を可視化するアプリを作ってみました。

動作の様子

Twitterに上げたらバズったので思ったよりみんなやってみたいんだなーと思いました

使い方

  1. コントローラーをクイックルワイパーの軸に固定する
    • 今回は養生テープを使いました
  2. アプリを起動する
  3. クイックルワイパーの仮想ヘッドに現実ヘッドを合わせる
  4. コントローラーのメニューボタンを押す
    • これによって仮想ヘッドが現実ヘッドに追従するようになります
  5. クイックルワイパーをかける

想定読者

UnityでのQuestのアプリを作ってみたい or 軽く作ったことがある方

先行事例

QuestのMRモードで掃除機をかけた場所を可視化

iPhoneのAR機能で掃除機を書けた場所を可視化

作り方

プレーンなQuestのMRアプリを作る

以下の手順は細かいところを端折った大雑把なものです。
詳細を知りたい方はこちらのページを見ることをおすすめします。
逆に細けえことは良いから楽をしたい方はこちらの記事のテンプレートプロジェクトを複製するといいです。

  1. Unityの3Dの空プロジェクトを立ち上げる
  2. Meta XR Interaction SDKをインポートする
  3. 画面上部のメニューのMeta → ツール → Building Blocksを開く
  4. Camera rigとPassthroughを追加する
    image.png

クイックルワイパーの仮想ヘッドで軌跡を描けるようにする

  1. 半透明でそれっぽい見た目の豆腐を作る
    • これと現実のクイックルワイパーのヘッドを揃えることで位置合わせをする
    • 幅はクイックルワイパーの幅に合わせて0.25mとする
      image.png
  2. 子オブジェクトを作ってTrailRendererをアタッチする
    • X軸で90度回転させて、更にTrailRendererの整列をトランスフォームZにすることで常に水平な軌跡になる
    • 幅を0.25にしたり、生存時間を十分長くしたり、半透明マテリアルにしたりする
      image.png

クイックルワイパーの現実ヘッドに仮想ヘッドが追従するようにする

  1. 仮想クリーナーヘッドのルートオブジェクトにParentConstraintコンポーネントをアタッチする
    • CameraRig/TrackingSpace/RightHandAnchorに追従するようにする
    • Y軸の位置及びX軸とZ軸は追従しないようにする
      image.png
  2. 以下のスクリプトをアタッチする
    • 追従開始時に位置と向きのオフセットを再計算しているのが肝です。これがないと右コントローラーと仮想ヘッドオブジェクトの相対的な位置と向きが正しくなりません。
CleanerHead.cs
using UnityEngine;
using UnityEngine.Animations;

public class CleanerHead : MonoBehaviour
{
    [SerializeField] TrailRenderer _trailRenderer;
    [SerializeField] ParentConstraint _parentConstraint;

    bool _isOperating;

    void Awake()
    {
        StopOperation();
    }

    void Update()
    {
        // デバッグ用にキーボードでも操作できるようにする
        if (OVRInput.GetDown(OVRInput.Button.Start) || Input.GetKeyDown(KeyCode.Space))
        {
            ToggleOperation();
        }
    }

    void ToggleOperation()
    {
        if (_isOperating)
        {
            StopOperation();
        }
        else
        {
            StartOperation();
        }
    }

    void StartOperation()
    {
        _isOperating = true;
        _trailRenderer.emitting = true;
        _parentConstraint.constraintActive = true;

        // 位置と向きのオフセットを再計算
        var targetTrans = _parentConstraint.GetSource(0).sourceTransform;
        var posOffset = targetTrans.InverseTransformPoint(transform.position);
        var rotOffset = Quaternion.Inverse(targetTrans.rotation) * transform.rotation;
        _parentConstraint.SetTranslationOffset(0, posOffset);
        _parentConstraint.SetRotationOffset(0, rotOffset.eulerAngles);
    }

    void StopOperation()
    {
        _isOperating = false;
        _trailRenderer.emitting = false;
        _parentConstraint.constraintActive = false;
    }
}

仮想ヘッドオブジェクトは最終的に以下の様になります
image.png

今後の課題

  • ハンドトラッキングでやりたい
    • 試したが、精度が低くてだめだった
    • コントローラーをクイックルワイパーに固定する準備作業がめんどくさすぎる
  • 軌跡の描画が汚い
    • 重なっている部分も1枚分だけ描画としたい
    • 折り返し部分が角々している

おわりに

MRアプリ開発は楽しいです!現実を拡張して便利にしていきましょう。

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?