Unity におけるカスタムカメラ実装 - 外部フレームデータソース
外部フレームデータソース(ExternalFrameSource)を使うと、開発者は EasyAR Sense にカスタムカメラ実装を拡張でき、特定のヘッドマウントデバイスやその他の入力デバイスをサポートできます。以下では、外部フレームデータソースの型構造とインターフェース定義を説明します。
開始前
外部フレームデータソースの種類
---
config:
class:
hideEmptyMembersBox: true
---
classDiagram
class FrameSource {
<<abstract>>
}
class ExternalFrameSource {
<<abstract>>
}
class ExternalDeviceFrameSource {
<<abstract>>
}
class ExternalDeviceMotionFrameSource:::EasyAR {
<<abstract>>
}
class ExternalDeviceRotationFrameSource:::EasyAR {
<<abstract>>
}
class ExternalImageStreamFrameSource:::EasyAR {
<<abstract>>
}
ExternalFrameSource --|> FrameSource
ExternalDeviceFrameSource --|> ExternalFrameSource
ExternalDeviceMotionFrameSource --|> ExternalDeviceFrameSource
ExternalDeviceRotationFrameSource --|> ExternalDeviceFrameSource
ExternalImageStreamFrameSource --|> ExternalFrameSource
classDef EasyAR fill:#6e6ce6,stroke:#333,color:#fff
上の図は、外部フレームデータソースの型構造を示しています。
入力データの違いに応じて、外部フレームデータソースは大きく 2 つに分けられます。
- 画像とデバイスモーションデータ入力拡張
- ExternalDeviceMotionFrameSource を継承して実装します。デバイスとその SDK が 6DoF のモーショントラッキングを提供し、仮想カメラの transform などの制御もデバイス SDK が担当します。
- ExternalDeviceRotationFrameSource を継承して実装します。デバイスとその SDK が 3DoF の回転トラッキングを提供し、仮想カメラの transform などの制御もデバイス SDK が担当します。
- 画像入力拡張
- ExternalImageStreamFrameSource を継承して実装します。画像入力のみを提供し、仮想カメラの transform などの制御は EasyAR が担当します。
これらの外部フレームデータソースを接続するときに利用できる AR 機能は、次のとおりです。
- 画像とデバイスモーションデータ入力拡張 ExternalDeviceMotionFrameSource
- Mega
- モーショントラッキング(デバイス自身が提供)
- 疎空間マップ
- 密空間マップ
- 画像トラッキング(モーション融合あり)
- クラウド画像認識
- オブジェクトトラッキング(モーション融合あり)
- 画像とデバイスモーションデータ入力拡張 ExternalDeviceRotationFrameSource
- Mega
- 画像トラッキング(モーション融合なし)
- クラウド画像認識
- オブジェクトトラッキング(モーション融合なし)
- 画像入力拡張 ExternalImageStreamFrameSource
- 画像トラッキング(モーション融合なし)
- クラウド画像認識
- オブジェクトトラッキング(モーション融合なし)
外部フレームデータソースのインターフェース定義
外部フレームデータソースを作成するときは、関連するインターフェースを実装する必要があります。以下では、それらの定義と使い方を説明します。
デバイス定義
FrameSource.IsHMD:
ヘッドマウントディスプレイかどうかを定義
ヘッドマウントディスプレイデバイスでのみ true に設定します。デバイスがヘッドマウントディスプレイの場合、診断情報はスクリーンではなく、カメラ前方の 3D ボード上に表示されます。AR 機能の一部は、ヘッドマウントディスプレイデバイス上で少し異なる動作をすることがあります。FrameSource.Display:
表示システムを定義
現在の表示の回転などの情報を提供します。
既定の表示情報を取得するには、Display.DefaultSystemDisplay または Display.DefaultHMDDisplay を使用できます。
通常、ヘッドマウントディスプレイでは Display.DefaultHMDDisplay を使用できます。
利用可能性
- FrameSource.IsAvailable:
利用可能性
frame source が使用できるかどうかを判定するために使います。
現在の実行デバイスまたは環境で frame source が利用できない場合、この値は false であるべきです。
この値が Optional.Empty の場合、FrameSource.CheckAvailability() コルーチンが呼び出されます。コルーチンが終了する前に FrameSource.IsAvailable を更新する必要があります。
利用可能性インターフェースは session の組み立て時に使われます。利用できないコンポーネントは選択されず、session 実行中にそのメソッドが呼び出されることもありません。 - FrameSource.CheckAvailability()(省略可):
frame source の利用可否を確認するコルーチン
FrameSource.IsAvailable が Optional.Empty の場合に呼び出されます。このコルーチンが終了するまで、session の組み立て処理はブロックされます。
session 原点
ExternalDeviceFrameSource.OriginType:
原点タイプ- XROrigin: デバイス SDK は Unity.XR.CoreUtils.XROrigin を原点として使用します。
- Custom: デバイス SDK はカスタム原点を使用します。ExternalDeviceFrameSource.Origin を指定する必要があります。
- None: デバイス SDK は原点を定義しません。
この場合、原点はシーンから自動的に選択または作成されますが、移動はしません。
session は SessionOrigin のセンターモードのみをサポートします。すべての target と target 配下のコンテンツは Unity の座標系内で常に移動するため、アプリケーション開発者は仮想オブジェクトの配置に十分注意する必要があります。ユーザーコンテンツの一部(物理システムなど)は正常に動作しない場合があります。Unity のワールド座標系に配置されたオブジェクトは、どの設定でも正しい位置に表示されることはありません。
ExternalDeviceFrameSource.Origin:
原点オブジェクト
ExternalDeviceFrameSource.OriginType が Custom の場合にのみ、自分の原点を定義します。それ以外のときは再定義する必要はありません。
仮想カメラ
- FrameSource.Camera:
仮想カメラ
カメラは session によって制御されず、カメラの transform と投影行列、および画像背景の描画は外部コードが制御する必要があります。
このカメラはヘッドマウントディスプレイ上でのみ使われ、診断テキストを目の前に表示するために使用されます。
ExternalDeviceFrameSource.OriginType が XROrigin の場合は定義不要です。EasyAR が Unity XR フレームワークで定義されたカメラを自動的に使用します。
物理カメラ
- FrameSource.DeviceCameras:
物理カメラのパラメータ
カメラフレームデータを提供する物理カメラです。カメラフレームデータが複数のカメラから提供される場合、一覧にはすべての物理カメラを含める必要があります。FrameSource.CameraFrameStarted が true のときに、正しい物理カメラパラメータを取得できることを確認してください。 - FrameSource.CameraFrameStarted:
カメラフレーム入力が開始済みかどうか
物理カメラが準備完了し、EasyAR にデータを送れる状態になったら true を返し、物理カメラが停止したら false を返します。FrameSource.CameraFrameStarted が false のとき、EasyAR は動作しません。FrameSource.CameraFrameStarted が true のときは、FrameSource.DeviceCameras のデータにアクセスでき、カメラフレームデータを継続的に EasyAR に入力できることを保証する必要があります。EasyAR はカメラフレームの入力が長時間続かないことを検出すると警告を表示し、機能が応答しない場合の切り分けを支援します。
物理カメラパラメータは実際のデバイスカメラと一致している必要があります。
- FrameSourceCamera.CameraType:
物理カメラの種類
たとえばヘッドマウントディスプレイのような前面カメラではないケースでは、通常は背面カメラを選択します。 - FrameSourceCamera.CameraOrientation:
デバイスの自然な向きで物理カメラ画像を表示するときに必要な時計回りの回転角
範囲は [0, 360) です。 - FrameSourceCamera.FrameSize:
画像サイズ - FrameSourceCamera.FrameRateRange:
フレームレート範囲
x をフレームレート範囲の下限、y を上限として定義します。 - DeviceFrameSourceCamera.AxisSystem:
頭部/物理カメラ pose と物理カメラ外部パラメータに使う座標軸系
すべての行列は同じ座標軸系を使う必要があります。データ定義が既知のシステムに合わない場合は、EasyAR に渡す前に座標軸変換を行ってください。 - DeviceFrameSourceCamera.Extrinsics:
物理カメラの外部パラメータ
通常はキャリブレーション済みの行列です。その座標軸は DeviceFrameSourceCamera.AxisSystem の定義に従う必要があります。外部パラメータの座標軸定義が実際の pose の座標軸定義と異なる場合、または DeviceFrameSourceCamera.AxisSystem の定義に合わない場合は、この値を設定する前に座標軸変換を行ってください。
session の開始と停止
- FrameSource.OnSessionStart(ARSession):
session 開始イベントの処理
session の組み立て時にこの frame source が選択された場合に有効です。
遅延初期化に使え、このメソッドで AR 専用の初期化処理を行えます。 - FrameSource.OnSessionStop():
session 停止イベントの処理
session の組み立て時にこの frame source が選択された場合に有効です。
このメソッドでは、FrameSource.OnSessionStart(ARSession) や session 実行中に作成されたリソースを破棄し、内部状態を復元できます。session が破棄される前に、このメソッドは必ず呼び出されます。session より先に frame source が破棄された場合、このメソッドは呼び出されず、session は Broken 状態に入ります。
入力フレーム
ExternalDeviceRotationFrameSource.HandleCameraFrameData(DeviceFrameSourceCamera, double, Image, CameraParameters, Quaternion):
カメラフレームデータの入力
デバイス SDK の API がすべてスレッドセーフであれば、どのスレッドからでも呼び出せます。
これらのデータは、物理カメラセンサーが露光した時点のものと一致している必要があります。30 fps または 60 fps での入力を推奨します。受け入れ可能な最小フレームレートは 2 ですが、一部のアルゴリズムの応答時間に影響します。可能であればカラー データを入力することを推奨します。これは Mega の効果に役立ちます。最高効率を得るには、元の YUV データを共有メモリでそのまま透過し、データポインタを直接 EasyAR に渡すようにデータチェーン全体を設計し、データ所有権に注意してください。ExternalDeviceMotionFrameSource.HandleRenderFrameData(double, Pose, MotionTrackingStatus):
レンダーフレームデータの入力ExternalDeviceRotationFrameSource.HandleRenderFrameData(double, Quaternion):
レンダーフレームデータの入力
デバイスデータの準備ができた後は、毎レンダーフレームで呼び出し、フレームを飛ばしてはいけません。これらのデータは、同じフレーム内で現在の Unity 仮想カメラを駆動しているデータと一致している必要があります。
- ExternalFrameSource.TryAcquireBuffer(int):
メモリプールからメモリブロックの取得を試行する
このメモリブロックは通常、カメラフレームの画像データを保存し、EasyAR に渡すために使用されます。 - ExternalFrameSource.ReceivedFrameCount:
EasyAR が受信したカメラフレーム数
EasyAR はこれを使ってデバイスのカメラフレーム入力の健全性を監視します。デバッグ用途にも使え、この値の増加が止まった場合は、通常、デバイスから EasyAR へのデータ供給が止まっていることを示します。
Unity メッセージ
以下のメッセージをスクリプトで使用する場合は、必ずベースクラスの実装を呼び出してください。
後続手順
- 外部入力フレームデータ を読み、カメラフレームデータとレンダーフレームデータを理解します。
- 画像とデバイスモーションデータ入力拡張 を作成します。
- 画像入力拡張 を作成します。