揚げログ

更新休止中・Karaageの活動報告とメモ

AR kit で顔面キャスアプリを作る (その4 transformから目の回転角を求める)

だいぶ間が空いてしまいました。

この間は、AR kit FaceTracking Configurationで、表情の値(blendshapes)を取得しましたが、今回は目の動きを取ってみたいと思います。

全体手順

  1. AR kitのFaceTrackingで、目の動きを数値データで取り出す
  2. ソケット通信でサーバーに送信
  3. クライアント側で数値を受信
  4. three.js VRMloaderでVRMデータを読み込む
  5. VRMデータに数値を反映させる

2, 3は、前回までで動作確認まで終わっています。

4, 5は次回の記事に多分書きます。

コード

下記コードは、1,2を行う処理で、func rendererは顔情報がアップデートされるたび(didUpdate)に呼ばれる関数です。

コードの全体は、

facecast_ios/eyeGaze.swift at master · krgpi/facecast_ios · GitHub

です。

class eyeGaze: NSObject, VirtualContentController { 
    var emitArray:[String: Float] = ["eyeL": 0.00, "eyeR": 0.00, "faceDir": 0.00]
//中略
    func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
        guard #available(iOS 12.0, *), let faceAnchor = anchor as? ARFaceAnchor
            else { return }
        
        emitArray["eyeL"] = asin(faceAnchor.leftEyeTransform.columns.2.x)
        emitArray["eyeR"] = asin(faceAnchor.rightEyeTransform.columns.2.x)
        emitArray["faceDir"] = asin(faceAnchor.transform.columns.2.x)

        do {
            let e = try JSONSerialization.data(withJSONObject: emitArray, options: .prettyPrinted)
            let str = String(bytes: e, encoding: .utf8)
            socket.socketIOClient.emit("chat message", str!)
        } catch  {
            print("err")
        }

    }
//後略
}

AR kit の Transformについて

ここで出てくる、leftEyeTransform, rightEyeTransform, transformは、いずれも

transform - ARAnchor | Apple Developer Documentation

にあるように、基準ベクトル(正面向き・まっすぐ前向き)から現在のベクトルへの変換行列です。3次元の変換行列なので、以下のようにパラメータを定めた時、

params 内容
d_{x} x方向への移動距離
d_{y} y方向への移動距離
d_{z} z方向への移動距離
\theta_{x} x軸周りの回転角
\theta_{y} y軸周りの回転角
\theta_{z} z軸周りの回転角

ただし、EyeTransformに関しては、

^\forall \theta_{z} = 0

AR kitでは、右手系(親指から順にx,y,z軸)を用いていて、目の奥から先に向かう軸をZ軸としています。

目はX, Y軸中心にしか回転しないので、Z軸回りの回転角が常に0です。

今回の計算

今回は、目の水平方向の回転を取り出したいので、 \theta_{y} を求めたいと思います。

^\forall \theta_{z} = 0 の時の3次元変換行列は、
\left(\begin{array}{rrrr}\cos{\theta_{y}} & 0 & -\sin{\theta_{y}} & d_{x}\\ \sin{\theta_{x}}sin{\theta_{y}} & cos{\theta_{x}} & \sin{\theta_{x}}cos{\theta_{y}}  & d_{y} \\ \cos{\theta_{x}}sin{\theta_{y}}  & -\sin{\theta_{x}} & \cos{\theta_{x}}cos{\theta_{y}}  & d_{z} \\0 & 0 & 0 & 1\\\end{array}\right)
です。

transformのデータ型は simd_float4x4 という型で、transform.colums.0, 1, 2, 3 という形で、まず列が取り出せます。

さらに、transform.colums.0.x, y, x, wという形で、行数を選択することができます。

ここで、 \theta_{y}=\arcsin({transform.colums.2.x}) となります。

まとめの図

f:id:en0qi:20190319111231j:plain
transform(simd_float4x4)

iPad Pro、便利ですね!!

次回はthree.jsを使ったウェブビューワーの作成の記事を投げます!