第2章 ARKit 堤 修一/@shu223
ワールド変換行列から向きを計算することもできますが、もっと手軽に、ARCameraにはカメラの向きをオイラー角(Euler angles)として取得できるeulerAnglesプロパティが用意されています。型はvector_float3です。
let angles = camera.eulerAngles // vector_float3
■仮想オブジェクトが常にカメラの方を向くようにする
さて、ここで「デバイスの移動や向きの変化に対するインタラクション」の例として、現実空間内に設置した仮想オブジェクトが常にユーザーの方を向くように実装してみましょう。
iOS 11でSCNNodeにlook(at:)メソッドが追加されました。このメソッドを使うと、引数に渡したワールド座標に向くように、SCNNodeオブジェクトのorientationを更新してくれます。
// 仮想オブジェクトをカメラの方に向ける virtualNode.look(at: pos)
便利なメソッドですが、単純にこれを使用するだけだと仮想オブジェクトがx, y, zの3軸すべてについて回転が起きる可能性があり、重力方向について傾いてしまう等、水平面に対して設置しているオブジェクトにとっては不自然な結果になってしまう場合があります。
そこで、重力方向に対しては回転を加えないよう、y軸に沿ってだけ回転させることにします。仮想オブジェクトのワールド座標とカメラのワールド座標の成すベクトルの、x-z平面における角度を計算し、その角度を打ち消すようにy軸に対する回転を与えます。
// カメラの位置を計算 let mat = SCNMatrix4(frame.camera.transform) let cameraPos = SCNVector3(mat.m41, mat.m42, mat.m43) // 仮想オブジェクトとカメラの成すベクトルの、x-z平面における角度を計算 let vec = virtualNode.position - cameraPos let angle = atan2f(vec.x, vec.z) // 仮想オブジェクトのrotationに反映 virtualNode.rotation = SCNVector4Make(0, 1, 0, angle + Float.pi)
これでデバイスを持って移動しても、仮想オブジェクトが常にユーザーの方を向くようになります。