6
9

More than 5 years have passed since last update.

【ARKit】ARアプリで使用する3Dプログラミングの行列

Last updated at Posted at 2019-01-19

この投稿はなに?

ARKit で ARアプリケーションを作成するには、3Dプログラミングが欠かせないことがわかりました。
iOS には、3Dプログラミングのためのフレームワーク SceneKit が用意されています。
この投稿では、SceneKit と ARKit で使用される 空間座標系 を表現するデータ型について、まとめてみました。

空間の情報は、行列で表現される

ARKit および SceneKit では、空間情報を表現するために「4行4列」の行列が多く使用されます。
空間情報は transform プロパティに格納されていることが多いようです。
行列型オブジェクト transform プロパティに対して、.columnsを参照すると、「行列の列」を配列要素のように取得できます。
この結果に対して、さらにインデックスを指定してアクセスすることもできます。
4列目の値を取得するには、columns.3と記述します。すると、「1行4列目, 2行4列目, 3行4列目, 4行4列目」の値が取得できます。

カメラのtransformから、4列目の値をすべて取得する
let positionInSpace = currentFrame.camera.transform.columns.3

この方法では、インデックスが 0 から始まることに注意 ですね。

空間情報に含まれる値

transform と呼ばれる空間情報には、以下の情報が含まれています。

  • 1列目: x軸方向の回転角
  • 2列目: y軸方向の回転角
  • 3列目: z軸方向の回転角
  • 4列目: 3D座標系(x, y, z)

これらの値が、列となっています。
前述の「カメラのtransformから、4列目の値をすべて取得する」コードでは .3 で、4列目の「3D座標系」を取得したことになります。

フレームワークごとに異なる行列の名称

空間を表現するために「4x4行列」が使われるのは、ARKit でも SceneKit でも同じですが、そのデータ型の名称が異なるようです。

worldTransform プロパティ

simd_float4x4 型。
この型のオブジェクトは、ARKit ではヒットテストの結果である ARHitTestResult のプロパティとして含まれている。

smid_float4x4 型

Float 型の値を含んでいる4行4列の行列です。
simd とは、Single Instruction / Multiple Data の略で、「1つの命令を複数の値に対して実行できる」という利点があるようです。

定義
struct simd_float4x4

「4行4列の行列」を表現するデータ型では、この simd_float4x4 が最もプリミティブなようです。

matrix_float4x4 型

ARKit のカメラの空間情報は matrix_float4x4 型で表現される。

定義
typealias matrix_float4x4 = simd_float4x4

定義を見ると、simd_float4x4 型のタイプエイリアス(別名称)になっています。

SCNMatrix4 型

構造体。
SceneKit の空間(シーン)に配置されるノードの空間情報は SCNMatrix4 型で表現される。
つまり、ノードの transform プロパティは SCNMatrix4 型オブジェクトです。
ARKit の現実空間において、ノードを追加したい場合は

iOS,tvOS,watchOSでの定義
struct SCNMatrix4

行列に含まれる値は、それぞれ...
m11, m12, m13, m14
m21, m22, m23, m24
m31, m32, m33, m34
m41, m42, m43, m44
をドットシンタックスで参照できます。
例えば、「3行4列目の値」にアクセスしたいなら .m34 と記述します。

データ型を変換する

例えば、ノードをカメラと同じ空間情報(transform プロパティ)に配置したいとします。
このとき、以下の点を留意しておく必要があります。

  • ノードの transform プロパティは、SCNMatrix
  • カメラの transform プロパティは、matrix_float4x4

この違いを吸収するには SCNMatrix 型イニシャライザを使って、カメラ空間情報と同じ値の SCNMatrix オブジェクトを生成します。

行列の型を変換する
let cameraTransform = SCNMatrix4(currentFrame.camera.transform)
        node.transform = cameraTransform

まとめ

何故、行列を表現するデータ型がこんなにたくさんあるのか?
4x4行列には、他にどんな値が含まれているのか?
いつか、名称が統一されるのか?
...など、混乱と不思議はつきませんが、現時点で自分が理解できるところをまとめておきました。
皆様からご指摘や助言等いただけると、とても嬉しいです。

6
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
9