MRが楽しい

MRやVRについて学習したことを書き残す

Sharingのメッセージでワールド座標を使ってTransformを共有する

本日は hololens の技術調査枠です。
Sharing でワールド座標を使って位置情報を共有する方法についてです。

以下の SharingTest シーンで作成したプロジェクトを前提とします。
bluebirdofoz.hatenablog.com

Sharing は以下のメッセージ拡張により、共有する情報を増やすことができます。
bluebirdofoz.hatenablog.com

複数人が同じものを同じ位置に見るアプリを作る場合、そのオブジェクトの Transform 情報を共有することになります。
しかし Sharing が行われる際、複数台の hololens 間では同一のワールド座標は共有されません。

これについては以下のページが詳しいです。
blog.xin9le.net
future-architect.github.io

記事に記載されている通り、HologramCollection の座標系が共通の座標系となります。
f:id:bluebirdofoz:20171011231108j:plain

よってそのまま Transform 情報を共有する場合、ワールド座標は使えません。
HologramCollection のローカル座標系を用いる必要があります。
docs.unity3d.com
docs.unity3d.com

ローカル座標系が利用できるのであればこちらがシンプルです。
しかし、アセットを流用する場合などワールド座標系を利用したい場合もあると思います。

そういった場合は各プロセス内の HologramCollection の座標で補正する仕組みを噛ませればワールド座標系で共有可能です。
・GameManager

  /// HologramCollection オブジェクトを指定
  [SerializeField, Tooltip("Sharingベースオブジェクト")]
  private GameObject p_SharingBaseObject;

  /// <summary>
  /// Position変換関数(ワールド座標→Sharing座標)
  /// </summary>
  /// <param name="a_worldPosition">ワールド座標Position</param>
  private Vector3 ChangePositionWorldToSharing(Vector3 a_worldPosition)
  {
    return new Vector3(
        a_worldPosition.x - p_SharingBaseObject.transform.position.x,
        a_worldPosition.y - p_SharingBaseObject.transform.position.y,
        a_worldPosition.z - p_SharingBaseObject.transform.position.z
    );
  }

  /// <summary>
  /// Position変換関数(Sharing座標→ワールド座標)
  /// </summary>
  /// <param name="a_sharingPosition">Sharing座標Position</param>
  private Vector3 ChangePositionSharingToWorld(Vector3 a_sharingPosition)
  {
    return new Vector3(
        a_sharingPosition.x + p_SharingBaseObject.transform.position.x,
        a_sharingPosition.y + p_SharingBaseObject.transform.position.y,
        a_sharingPosition.z + p_SharingBaseObject.transform.position.z
    );
  }

  /// <summary>
  /// Rotation変換関数(ワールド座標→Sharing座標)
  /// </summary>
  /// <param name="a_worldRotation">ワールド座標Rotation</param>
  private Quaternion ChangeRotationWorldToSharing(Quaternion a_worldRotation)
  {
    return Quaternion.Euler(
        a_worldRotation.eulerAngles.x - p_SharingBaseObject.transform.rotation.eulerAngles.x,
        a_worldRotation.eulerAngles.y - p_SharingBaseObject.transform.rotation.eulerAngles.y,
        a_worldRotation.eulerAngles.z - p_SharingBaseObject.transform.rotation.eulerAngles.z
    );
  }

  /// <summary>
  /// Rotation変換関数(Sharing座標→ワールド座標)
  /// </summary>
  /// <param name="a_sharingRotation">Sharing座標Rotation</param>
  private Quaternion ChangeRotationSharingToWorld(Quaternion a_sharingRotation)
  {
    return Quaternion.Euler(
        a_sharingRotation.eulerAngles.x + p_SharingBaseObject.transform.rotation.eulerAngles.x,
        a_sharingRotation.eulerAngles.y + p_SharingBaseObject.transform.rotation.eulerAngles.y,
        a_sharingRotation.eulerAngles.z + p_SharingBaseObject.transform.rotation.eulerAngles.z
    );
  }