ARKitでオクルージョン


オクルージョンとは

オクルージョンとは手前にある物体が背後にある物体を隠して見えないようにする状態のことです。

現実世界では後ろにある物体が前にある物体に隠れるのは当然ですが、ARの世界では物体の表示をうまいことコントロールしないと、前後関係がうまく表現できません。

以下にオクルージョンの例をあげます。

ナイアンティックの例

まずは、ナイアンティックの動画です。バーチャルのピカチュウが現実の人の影に隠れています。


https://youtu.be/7ZrmPTPgY3I

テクテクテクテクの例

この前僕がテクテクテクテクを外苑前で使った時に撮った以下の画像もオクルージョンしてます。

ARKitでオクルージョン

ARKitでも平面に関してならレンダリングを工夫すれば行うことができます。

決めてはrenderingOrderです。

renderingOrder

SCNNodeのパラメータのrenderingOrderをいじるだけでオクルージョンができます。

平面検出については、[iOS 11][ARKit] 平面の検出について #WWDC2017
あたりの記事を読んでいただいた上で、以下のようなお決まりのパターンのplaneAnchorの取得から平面のNodeを置くコードを見ていきましょう。

extension ViewController: ARSCNViewDelegate {
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard let planeAnchor = anchor as? ARPlaneAnchor else {
            return
        }
        let extent = planeAnchor.extent
        let plane = SCNPlane(width: CGFloat(extent.x), height: CGFloat(extent.z))
        let planeNode = SCNNode(geometry: plane)
        planeNode.name = "arPlane"
        planeNode.renderingOrder = -1
        planeNode.eulerAngles.x = -.pi/2
        node.addChildNode(planeNode)
    }
}

注目すべきなのは、

planeNode.renderingOrder = -1

これをすることで、planeNodeを描画する順番が一番最初になります。なぜならSCNNodeのrenderingOrderのデフォルト値は0だからです。

0より-1のほうが小さいので必ず先に平面が描画され、その結果、以下の赤いBoxNodeは平面と重なったときに隠れます。

別に-1じゃなくても良いんですが、-1を使うと、他のNodeには0が入ってるので手っ取り早いですね。

このrenderingOrderをコントロールすることで、例えばSceneKit の SCNNode のレンダリングオーダーでどこでもドア的表現をするのようなこともできます。

まとめ

  • 平面にNodeを貼ることができれば、その後ろに物体を隠してオクルージョンができる
  • Nodeさえ表面にうまいこと貼ることができれば机以外にもオクルージョンできるかも?