カメラへのアクセス
機能の有効化
この機能を使用するには、以下のOpenXRのプ ロジェクト設定でCamera Accessにチェックする必要があります。
Project Settings > XR Plug-in Management > OpenXR (Androidタブ)
機能の設定
カメラフレームへのアクセス機能には4つの設定があります。
- Direct Memory Access Conversion
- CPUによるフレーム変換の前に、アプリケーションがカメラメモリへのアクセス方法を決定するために使用します。デバイスによっては性能が向上する場合もありますが、性能が低下する場合もあります。
- CPU Frame Cache Size
- XRCpuImage.ConvertAsyncのキャッシュフレームのサイズで、非同期変換要求をキューに入れることができる数を定義します。上限に達すると、古いリクエストは期限切れになります。
- High Priority Async Conversion
- 変換スレッドを優先度の高いスレッドとして扱うかどうかを決定するために、アプリケーションによって使用されます。
- Cache Frame Before Async Conversion
- CPUのキャッシュフレームに依存することなく、要求時にフレームをキャッシュすることで非同期変換を保証します。Direct Memory Access Conversionが有効な場合は無視されます。
CPU上のデバイスカメラ画像の取得
新しいカメラフレームがサブシステムで利用可能になるたびに、AR Camera Manager
はframeReceived
イベントを発行します。このイベントをサブスクライブすることで、他のスクリプトができるだけ早いタイミングで最新のカメラフレームを取得し、そのフレームに対して処理を実行できるようになります。
カメラフレームが利用可能になると、カメラマネージャーのTryAcquireLatestCpuImage
関数は、選択されたデバイスカメラからの単一のRaw画像を表すXRCpuImage
オブジェクトを返します。この画像のRawピクセルデータは、NativeArray<byte>
を返すXRCpuImageのConvert
関数で抽出できます。
Snapdragon Spacesは、XRCpuImage.ConvertAsync
を通じてフレームの非同期変換もサポートしています。
この場合、返されたAsyncConversion
オブジェクトをポーリングしてAsyncConversion.GetData<byte>
でデータを取得するか、NativeArray<byte>
引数を持つコールバックを提供して変換が完了した際に実行します。
AR Camera Managerのコンポーネントは、XR Originの作成時に自動的にシーンのHierarchyに追加されます。AR Camera Managerのコンポーネントが有効になっている間は、OpenXRのランタイムアプリケーションからカメラフレームが要求されます。シーンでカメラフレームへのアクセスを必要としない場合は、このコンポーネントを無効にすることを検討してください。
XR Originを作成すると、AR Camera Backgroundのコンポーネントが自動的にシーンのHierarchyに追加されますが、Snapdragon Spacesはバージョン0.20.0以降これをサポートしていません。レンダリングの問題を避けるには、この コンポーネントを無効にする必要があります。
XRCpuImage
オブジェクトは変換後に明示的に破棄する必要があります。これにはXRCpuImage
のDispose
関数を使用します。XRCpuImage
オブジェクトを廃棄しないと、カメラアクセスのサブシステムが破壊されるまでメモリリークする可能性があります。
変換前にNativeArray<byte>
を確保する場合、このバッファもコピーまたは操作後に破棄する必要があります。これを行うには、NativeArray<T>
のDispose
関数を使用します。NativeArray<byte>
を破棄しないと、カメラアクセスのサブシステムが破棄されるまでメモリがリークします。
AsyncConversion
オブジェクトは、データの使用後に明示的に破棄する必要があります。これにはAsyncConversion
の Dispose
関数を使用します。AsyncConversion
オブジェクトを破棄しないと、カメラアクセスのサブシステムが破棄されるまでメモリリークする可能性があります。
XRCpuImage.ConvertAsync
を使用してコールバック関数を提供する場合、提供されたNativeArray<byte>
のデータバッファを破棄する必要はありません。変換データは、コールバックが終了した際にカメラのサブシステムによって破棄されます。
frameReceived
、TryAcquireLatestCpuImage
、XRCpuImage.Convert
、XRCpuImage.ConvertAsync
の使用方法の詳細については、Unityのドキュメントを参照してください。
カメラフレームへのアクセスは、使用するデバイスによっては初期化に数秒かかる場合があります。サブシステムが 正常に初期化される前にフレームにアクセスしようとしないでください。エラーを避けるため、AR Foundation APIからframeReceived
イベントを使用することを強く推奨します。
以下のサンプルコードは、frameReceived
イベントが発生したときに、AR Camera ManagerにCPU上のカメラ画像を要求します。成功すれば、XRCpuImage
のRawピクセルデータを直接管理されているTexture2D
のGetRawTextureData<byte>
バッファに抽出し、その後Apply
関数でテクスチャバッファを適用します。最後に、ターゲットのRawImage
のテクスチャを更新し、アプリのUIで新しいフレームが見えるようにします。
public RawImage CameraRawImage;
private ARCameraManager _cameraManager;
private Texture2D _cameraTexture;
private XRCpuImage _lastCpuImage;
public void Start()
{
_cameraManager.frameReceived += OnFrameReceived;
}
private void OnFrameReceived(ARCameraFrameEventArgs args)
{
_lastCpuImage = new XRCpuImage();
if (!_cameraManager.TryAcquireLatestCpuImage(out _lastCpuImage))
{
return;
}
UpdateCameraTexture(_lastCpuImage);
}
private unsafe void UpdateCameraTexture(XRCpuImage image)
{
var format = TextureFormat.RGBA32;
if (_cameraTexture == null || _cameraTexture.width != image.width || _cameraTexture.height != image.height)
{
_cameraTexture = new Texture2D(image.width, image.height, format, false);
}
var conversionParams = new XRCpuImage.ConversionParams(image, format);
var rawTextureData = _cameraTexture.GetRawTextureData<byte>();
try
{
image.Convert(conversionParams, new IntPtr(rawTextureData.GetUnsafePtr()), rawTextureData.Length);
}
finally
{
image.Dispose();
}
_cameraTexture.Apply();
CameraRawImage.texture = _cameraTexture;
}
以下のテクスチャフォーマットがAR Camera Managerでサポートされています。
RGB24
RGBA32
BGRA32