NRFrame.GetTrackables を読み解いてみる

概要

ImageTracking の仕組みを理解するために NRFrame.GetTrackables を読み解いてみます。 個人的な読解結果であるため誤りが含まれている可能性があることをご了承ください。

目次

確認環境

  • NRSDK 1.2.1

解説

拾い読み

NRFrame.GetTrackables から続く処理を拾い読みしました。以下が要点かと思います。

  • NRFrame.GetTrackables
    • NRTrackableManager.GetTrackables
      • UpdateTrackables を呼び出す
      • m_AllTrackables を m_NewTrackables と m_OldTrackables に振り分ける
    • NRTrackableManager.UpdateTrackables
      • trackablelist_handle = NativeTrackable.CreateTrackableList()
      • NativeTracking.UpdateTrackables(trackablelist_handle, trackable_type)
        • trackable_type : TrackableType (BASE/PLANE/IMAGE)
      • count = NativeTrackable.GetSize(trackablelist_handle)
      • count 回繰り返す
        • trackable_handle = NativeTrackable.AcquireItem(trackablelist_handle, index)
        • Create(trackable_handle, m_NativeInterface) を呼び出す
      • NativeTrackable.DestroyTrackableList
    • NRTrackableManager.Create
      • trackableType = NativeTrackable.GetTrackableType(trackable_handle)
      • trackableType が TRACKABLE_IMAGE の場合に NRTrackableImage インスタンスを生成する
      • m_TrackableTypeDict, m_AllTrackables に NRTrackableImage インスタンスを登録する

ここまで読んで、TrackingImageDatabase (ScriptableObject) は何に使われているのか疑問に思いました。 TrackingImageDatabase が関連している処理を探して読んでいくと、NRSessionBehaviour から始まる処理で使用されていることがわかりました。 一連の処理では以下が要点になると思います。

  • NRSessionBehaviour
    • NRSessionManager.CreateSession
      • NRDevice.Init
      • NativeInterface.NativeTracking.Create
        • NativeApi.NRTrackingCreate(ref m_TrackingHandle)
        • NativeInterface.TrackingHandle = m_TrackingHandle
      • NativeAPI.NativeTracking.SetTrackingMode(TrackingMode)
      • DeployData
        • database = SessionConfig.TrackingImageDatabase
        • ZipUtility.UnzipFile(database.RawData, database.TrackingImageDataOutPutPath, NativeConstants.ZipKey)
          • TrackingImageDataOutPutPath は [Application.persistentDataPath]/TrackingImageData/
    • NRSessionManager.StartSession
      • SetAppSettings(SessionConfig.OptimizedRendering)
      • NativeAPI.NativeTracking.Start()
        • NativeApi.NRTrackingStart
      • NativeAPI.NativeHeadTracking.Create()
        • NativeApi.NRHeadTrackingCreate
    • NRSessionManager.SetConfiguration
      • NativeConfigration.UpdateConfig
        • NativeApi.NRConfigCreate(m_NativeInterface.TrackingHandle, ref m_ConfigHandle)
          • m_ConfigHandle が 0 の場合のみ行う
        • NRSessionConfig.ImageTrackingMode が DISABLE の場合
          • NativeTrackableImage.DestroyDataBase(m_DatabaseHandle)
            • m_DatabaseHandle が 0 以外の場合のみ行う
        • NRSessionConfig.ImageTrackingMode が ENABLE の場合
          • m_DatabaseHandle = NativeTrackableImage.CreateDataBase()
          • NativeTrackableImage.LoadDataBase(m_DatabaseHandle, TrackingImageDataPath)
            • TrackingImageDataPath : NRSessionConfig.TrackingImageDatabase.TrackingImageDataPath
              • [Application.persistentDataPath]/TrackingImageData/[DB_GUID] ディレクト
          • NativeApi.NRConfigSetTrackableImageDatabase(m_NativeInterface.TrackingHandle, m_ConfigHandle, m_DatabaseHandle)

要点を整理する

NRFrame.GetTrackable

NRFrame.GetTrackable の API は以下の様になっており、引数 trackables には検出した結果を格納する List、引数 filter には結果を絞り込む条件を指定します。

void NRFrame.GetTrackable<T>(List<T> trackables, NRTrackableQueryFilter filter) where T : NRTrackable

NRTrackableQueryFilter は All と New の 2 種類です。 NRTrackable のサブクラスは NRTrackableImage と NRTrackablePlane があり、T にはいずれかを指定します。

NRFrame.GetTrackable では、NRTrackableManager.GetTrackables を呼び出しています。引数は NRFrame.GetTrackables と同じです。 NRTrackableManager.GetTrackables では以下を行います。

  • NRTrackableManager.UpdateTrackables を呼び出して AllTrackables (List<NRTrackable>) を更新する
  • AllTrackables に新しく追加された NRTrackable を NewTrackables (List<NRTrackable>) に格納する
  • filter が All であれば AllTrackables の NRTrackable を trackables に格納する
  • filter が New であれば NewTrackables の NRTrackable を trackables に格納する

NRTrackableManager.UpdateTrackables では、Native API を呼び出して AllTrackables を更新します。 UpdateTrackables の引数には TrackableType が渡されます。 TrackableType は型パラメータの T から決定されます。 T が NRTrackableImage の場合は TrackableType は TRACKABLE_IMAGE、T が NRTrackablePlane の場合は TrackableType は TRACKABLE_PLANE になります。

NRTrackableManager.UpdateTrackables は以下の疑似コードの様に Native API を呼び出します。

void UpdateTrackables(TrackableType trackable_type)
{
    UInt64 trackable_list_handle;
    int list_size;
    NRTrackableListCreate(session_handle, ref trackable_list_handle);
    NRTrackingUpdateTrackables(session_handle, trackable_type, trackable_list_handle);
    NRTrackableListGetSize(session_handle, trackable_list_handle, ref list_size);
    for (int index = 0; index < list_size; index++)
    {
        UInt64 trackable_handle;
        TrackableType out_trackable_type;
        NRTrackableListAcquireItem(session_handle, trackable_list_handle, index, ref trackable_handle);
        NRTrackableGetType(session_handle, trackable_handle, ref out_trackable_type);
        if (out_trackable_type == TRACKABLE_PLANE) AllTrackables.Add(NRTrackablePlane(trackable_handle));
        if (out_trackable_type == TRACKABLE_IMAGE) AllTrackables.Add(NRTrackableImage(trackable_handle));
    }
    NRTrackableListDestroy(session_handle, trackable_list_handle);
}

上記のコードにおいて、session_handle は NativeInterface.TrackingHandle です。 NativeInterface.TrackingHandle は NRSessionManager.CreateSession の過程で設定されます。 これについては後ほど説明します。

以上で、NRFrame.GetTrackable から始まる一連の処理は終了です。 Native API を使用して ImageTracking を行っていることが分かります。

ImageTracking に関連する初期化処理

ここまで TrackingImageDatabase (ScriptableObject) は全く登場しませんでした。 ImageTracking には不要なのでしょうか? これについては NRSessionManager の Awake, Start の処理を見ていくことで理解が深まります。

NRSessionManager の Awake, Start では NRSessionManager の CreateSession, StartSession, SetConfiguration を呼び出しています。 これらの過程では以下に示す ImageTracking に関連する初期化処理が行われています。

  • NativeInterface.TrackingHandle の初期化

TrackingHandle の値は Native API から取得されます。 疑似コードで示すと以下の様になります。

UInt64 tracking_handle;
NRTrackingCreate(ref tracking_handle);
NativeInterface.TrackingHandle = tracking_handle;
  • TrackingImageDatabase データの展開

TrackingImageDatabase データは SessionConfig.TrackingImageDatabase.RawData に byte[] として保持しています。 この RawData は zip アーカイブのデータになっており、unzip して [Application.persistentDataPath]/TrackingImageData/ に展開されます。

  • ImageTracking の有効化/無効化

SessionConfig.ImageTrackingMode が ENABLE の場合には ImageTracking を以下の疑似コードの処理で有効化します。 session_handle は NativeInterface.TrackingHandle で、trackable_image_database_directory は SessionConfig.TrackingImageDatabase.TrackingImageDataPath です。 TrackingImageDataPath は [Application.persistentDataPath]/TrackingImageData/[DB_GUID]/ です。

UInt64 config_handle;
UInt64 trackable_image_database_handle;
NRConfigCreate(session_handle, ref config_handle);
NRTrackableImageDatabaseCreate(session_handle, ref trackable_image_database_handle);
NRTrackableImageDatabaseLoadDirectory(session_handle, trackable_image_database_handle, trackable_image_database_directory);
NRConfigSetTrackableImageDatabase(session_handle, config_handle, trackable_image_database_handle);

SessionConfig.ImageTrackingMode が DISABLE の場合には ImageTracking を以下の疑似コードの処理で無効化します。 session_handle は NativeInterface.TrackingHandle で、trackable_image_database_handle は有効化した時の値、trackable_image_database_handle は 0 です。

UInt64 config_handle;
NRConfigCreate(session_handle, ref config_handle);
NRTrackableImageDatabaseDestroy(session_handle, trackable_image_database_handle);
NRConfigSetTrackableImageDatabase(session_handle, config_handle, trackable_image_database_handle);

以上で、初期化処理は終了です。TrackingImageDatabase のデータは RawData に保持しており、unzip した上で Load しています。