深度を使って画面上の地点を現実世界の位置に変換する
ARDK 3.0の深度マップ出力により、平面やメッシュを使用せずに、ARシーンにオブジェクトを動的に配置することができます。 この例では、深度出力をもとに画面上の地点を選択し、オブジェクトを配置する方法を解説します。
前提条件
Lightship ARを有効にしたUnityのプロジェクトが必要です。 詳細については、 ARDK 3 のインストールを参照してください。
ヒント
初めて深度を使うのであれば、 Accessing and Displaying Depth Information は、深度のより単純な使用例を提供しており始めやすいです。
手順
メインシーンがAR対応でない場合は、次のように設定します。
-
Main Camera を削除します。
-
ARSession と XROrigin を階層に追加し、 AR Occlusion Manager Component をどちらかに追加します。
-
深度のピッキングとプレハブの配置を処理するスクリプトを作成します。
Depth_ScreenToWorldPosition
と名付け、対応するコードを追加する。
クリックするとDepth_ScreenToWorldPositionスクリプトが表示されます。
using Niantic.Lightship.AR.Utilities;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystem; public class Depth_ScreenToWorldPosition : MonoBehaviourARSubsystems;
public class Depth_ScreenToWorldPosition : MonoBehaviour
{
public AROcclusionManager _occMan;
public ARCameraManager _arCameraManager;
public Camera _camera;
public GameObject _prefabToSpawn;
private Matrix4x4 m_DisplayMatrix;
XRCpuImage? depthimage;
private void OnEnable()
{
_arCameraManager.frameReceived += OnCameraFrameEventReceived;
}
private void OnDisable()
{
_arCameraManager.frameReceived -= OnCameraFrameEventReceived;
}
private void OnCameraFrameEventReceived(ARCameraFrameEventArgs args)
{
// 画面から画像への変換をキャッシュ
if (args.displayMatrix.HasValue)
{
#if UNITY_IOS
m_DisplayMatrix = args.displayMatrix.Value.transpose;
#else
m_DisplayMatrix = args.displayMatrix.Value;
#endif
}.
}
void Update()
{
if (!_occMan.subsystem.running)
{
return;
}
if (_occMan.TryAcquireEnvironmentDepthCpuImage(out
var image))
{
depthimage?.Dispose();
depthimage = image;
}
else
{
return;
}.
#if UNITY_EDITOR
if (Input.GetMouseButtonDown(0))
{
var screenPosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
#else
if (Input.touches.Length > 0) {
var screenPosition = Input.GetTouch(0).position;
#endif
if (depthimage.HasValue)
{
// Sample eye depth
var uv = new Vector2(screenPosition.x / Screen.width, screenPosition.y / Screen.height);
var eyeDepth = depthimage.Value.Sample<float>(uv, m_DisplayMatrix);
// ワールド位置を取得
var worldPosition =
_camera.ScreenToWorldPoint(new Vector3(screenPosition.x, screenPosition.y, eyeDepth));
//デプスマップ上にモノをスポーンする
Instantiate(_prefabToSpawn, worldPosition, Quaternion.identity);
}.
}
}
}
Depth_ScreenToWorldPosition
スクリプトを、XROrigin
のコンポーネン トとして、 ** Hierarchy **に追加します:- Hierarchy ウィンドウで、
XROrigin
を選択し、 Inspectorで、 Add Component をクリックします。 Depth_ScreenToWorldPosition
スクリプトを検索し、選択します。
- Hierarchy ウィンドウで、
- シーンにスポーンするオブジェクトとして使用するため、 Cube を作成します:
- Hierarchyで右クリックし、 Create メニューで、 3D Object にマウスオーバーし、 Cubeを選択します。
- 新しい Cube オブジェクトを Hierarchy から Assets ウィンドウにドラッグしてプレハブを作成し、 Hierarchyから削除します。 ( Assets ウィンドウの Cube は残るはずです)。
Depth_ScreenToWorldPosition
スクリプトのフィールドを割り当てます:- Hierarchy ウィンドウで、
XROrigin
を選択し、 Inspector ウィンドウで、Depth_ScreenToWorldPosition
Component を展開します。 XROrigin
を Occ Man フィールドに割り当てます。- メインカメラ を カメラ フィールドに割り当てます。
- メインカメラを _arCameraManagerフィールドに割り当てます。
- 新しい Cube プレハブを Prefab to Spawn フィールドに割り当てます。
- Hierarchy ウィンドウで、
- Build Settings(ビルド設定) を開き、 Build and Run(ビルドと実行) をクリックしてデバイスにビルドし、試して みましょう。