ARkit

ARFaceTrackingConfiguration()

2료일 2023. 7. 12. 03:55

1. 먼저 기기에서 지원을 확인을 하는지 Appdelgate에서 확인을 한다.

if !ARFaceTrackingConfiguration.isSupported {
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
                
                let alert = UIAlertController(title: "Unsupported Device", message: "This app requires TrueDepth Camera with iOS 11.0+", preferredStyle: .alert)
                
                alert.addAction(UIAlertAction(title: "Close", style: .default) { action in
                    exit(0)
                })
                
                self.window?.rootViewController?.present(alert, animated: true)
            }
        }

2. ViewWillApear 수정

let configuration = ARFaceTrackingConfiguration()
// TODO: 3) 얼굴 인식을 사용하는 앱은 세션을 시작할 때 마다 트래킹을 리셋해주고, 존재하는 anchor를 지워주어야 한다.
sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])

뷰가 appear될때마다 트레킹과 존재 anchor reset해준다

3. render(_ : nodeFor) delegate 메서드 구현

    var contentNode: SCNReferenceNode? = nil

    // TODO: 4) 인식된 Face Anchor에 3D 콘텐트가 붙은 SCNNode를 붙여준다.
    func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
        guard anchor is ARFaceAnchor else {
            return nil
        }

        // Main Bundle에서 로봇 url가져오기
        guard let resourceUrl = Bundle.main.url(forResource: "robotHead", withExtension: "scn", subdirectory: "Models.scnassets") else {
            return nil
        }

        // 해당 URL로 SCNReferenceNode 생성
        guard let contentNode = SCNReferenceNode(url: resourceUrl) else {
            return nil
        }
        self.contentNode = contentNode
        self.contentNode?.load()

        // contentNode로부터 왼쪽, 오른쪽 눈 Node를 가져오기

        return self.contentNode
        }

ARFaceAnchor에서는 여러 얼굴이 있을 경우 가장 크거나 가장 선명하게 인식할 수 있는 얼굴을 고른다.

ARKit은 앵커의 SceneKit 노드를 관리하고 각 프레임에서 해당 노드의 위치와 방향을 업데이트하므로 해당 노드에 추가하는 모든 SceneKit 콘텐츠는 사용자의 얼굴의 위치와 방향을 자동으로 tracking

ARSCNViewDeleagate의 함수인데 이 함수를 통해 ARAnchor를 기반으로 새로운 노드생성

4. 왼쪽눈 오른쪽눈 각각을 노드로 생성후 업데이트 render함수생성

    var leftEyeNode: SCNNode? {
        return contentNode?.childNode(withName: "eyeLeft", recursively: true)
    }
    // 로봇 오른쪽 눈
    var rightEyeNode: SCNNode? {
        return contentNode?.childNode(withName: "eyeRight", recursively: true)
    }
    func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
      guard let anchor = anchor as? ARFaceAnchor else { return }

      if let leftEyeBlink = anchor.blendShapes[.eyeBlinkLeft] as? Float,
         let rightEyeBlink = anchor.blendShapes[.eyeBlinkRight] as? Float {
          leftEyeNode?.scale.z = 1 - leftEyeBlink
          rightEyeNode?.scale.z = 1 - rightEyeBlink
      }

    }

ARKit은 사용자가 눈을 깜빡이고, 말하고, 다양한 표현을 할 때에도 사용자의 얼굴 모양에 맞게 얼굴 메쉬를 업데이트!!

표시된 얼굴 모델이 사용자의 표현을 따르도록 하려면, renderer(_:didUpdate:for:) delegate 콜백에서 업데이트된 얼굴 메쉬를 검색한다.