15
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

ARKit 3 + SceneKit で People Occlusion を実現する

概要

  • ARKit 3 の People Occlusion を使用したサンプルアプリを動かす
  • Storyboard の状態を修正せず、ソースコードだけで実現する

People Occlusion とは

ARKit 2 までは、AR コンテンツは背景の画像の上にオーバーレイ描画されるだけだった。遠くに置いた AR コンテンツの前に人がいても、ARコンテンツは隠されずに表示されてしまっていた。

ARKit 3 の People Occlusion を使うと、仮想コンテンツと人の距離を考慮して表示してくれる。具体的には、人の位置が仮想コンテンツの位置よりもカメラに近い場合には、仮想コンテンツを隠すように描画する。

iOS 13 - 特長 - Apple(日本)

ピープルオクルージョン
ARコンテンツが人の手前や後ろに自然に現れるので、AR体験が一段と臨場感あふれるものになりました。楽しいグリーンバックのエフェクトもアプリケーションで使えます。

People Occlusion は A12/A12X Bionic 以降を搭載していないと使えない

iOS 13 - 特長 - Apple(日本)

iPhone XR以降、11インチiPad Pro、12.9インチiPad Pro(第3世代)、iPad Air(第3世代)、iPad mini(第5世代)で利用できます。

Augmented Reality - ARKit 3 - Apple Developer

People Occlusion and the use of motion capture, simultaneous front and back camera, and multiple face tracking are supported on devices with A12/A12X Bionic chips, ANE, and TrueDepth Camera.

今回の環境

  • Xcode 11.0
  • ARKit 3
  • SceneKit
  • Swift 5.1
  • iPhone 11 Pro + iOS 13.0

プロジェクトの作成

Xcode にてテンプレートから iOS + Argumented Reality App を選択する。

people-occlusion-1.png

以下のオプションを選択する。

  • Language: Swift
  • Content Technology: SceneKit
  • User Interface: Storyboard

people-occlusion-2.png

プロジェクトを作成すると AppDelegate.swift と ViewController.swift という Swift のソースコードが用意される。

people-occlusion-3.png

ソースコード

ViewController.swift を以下のコードに置き換える。

import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set the view's delegate
        sceneView.delegate = self

        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true

        // シーンを生成
        let scene = SCNScene()

        // Set the scene to the view
        sceneView.scene = scene

    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        // Create a session configuration
        let configuration = ARWorldTrackingConfiguration()

        // 環境マッピングを有効にする
        configuration.environmentTexturing = .automatic

        // People Occlusion が使える端末か判定
        var message:String;
        if ARWorldTrackingConfiguration.supportsFrameSemantics(.personSegmentationWithDepth) {
            // People Occlusion を使用する
            configuration.frameSemantics = .personSegmentationWithDepth
            message = "Ok! This device supports people occulusion."
        } else {
            message = "No! This device don't support people occulusion."
        }
        print("\(message)")

        // 表示するテキストを用意
        let depth:CGFloat = 0.2 // テキストの厚さ0.2m
        let text = SCNText(string: message, extrusionDepth: depth)
        text.font = UIFont.systemFont(ofSize: 1.0)

        // テキストの色と質感を用意
        let m1 = SCNMaterial()
        m1.diffuse.contents = UIColor.red // 前面に赤色
        // 鏡面反射感を出す
        m1.lightingModel = .physicallyBased
        m1.metalness.contents = 1.0
        m1.metalness.intensity = 1.0
        m1.roughness.intensity = 0.0
        // back material
        let m2 = SCNMaterial()
        m2.diffuse.contents = UIColor.green // 背面に緑色
        m2.lightingModel = .physicallyBased
        m2.metalness.contents = 1.0
        m2.metalness.intensity = 1.0
        m2.roughness.intensity = 0.0
        // extruded sides material
        let m3 = SCNMaterial()
        m3.diffuse.contents = UIColor.blue // 側面に青色
        m3.lightingModel = .physicallyBased
        m3.metalness.contents = 1.0
        m3.metalness.intensity = 1.0
        m3.roughness.intensity = 0.0
        text.materials = [m1, m2, m3] // テキストの色と質感をセット

        // テキストノード作成して、配置する場所を決める
        let textNode = SCNNode(geometry: text)
        textNode.position = SCNVector3(-0.5, -1.5, -0.5)

        // AR空間にテキストノードを追加
        sceneView.scene.rootNode.addChildNode(textNode)

        // Run the view's session
        sceneView.session.run(configuration)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        // Pause the view's session
        sceneView.session.pause()
    }
}

実機での実行結果

実機 (iPhone 11 Pro + iOS 13.0) にインストールして実行してみる。
iPhone 11 Pro は A12 Bionic 以降を搭載しているので People Occlusion が使える。

手の位置を考慮して AR コンテンツが描画されている。手が前に来ると AR コンテンツの一部が隠れる。ARKit 2 ではこれができなかった。

people-occlusion-4.jpg

people-occulusion.gif

参考資料

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
15
Help us understand the problem. What are the problem?