iOS/iOS 개발

iOS - BlendShapes 활용하기

포도 동 2021. 5. 27. 17:36

blendShapes를 활용할 head.scn 에셋과 그 안에 leftEye라는 chileNode가 있다고 가정합니다.

* 일반적인 .dae 3D 에셋을 XCODE로 불러오면 .scn 파일로 변환할 수 있습니다.

@IBOutlet var sceneView: ARSCNView!

var headNode: SCNNode?
var leftEyeNode: SCNNode?

먼저, ARKit과 SceneKit을 import 해줍니다.

그리고 화면을 나타낼 sceneView, 에셋을 연결할 headNode와 leftEyeNode를 SCNNode로 선언합니다.

 

override func viewDidLoad() {
	sceneView.delegate = self
}

ARSCNViewDelegate를 채택해줍니다.

 

그 후, ARSCNViewDelegate의 renderer 함수를 구현합니다.

func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
        guard let faceAnchor = anchor as? ARFaceAnchor else { return nil }
        
        headNode = SCNReferenceNode(named: "head")
        leftEyeNode = headNode?.childNode(withName: "leftEye", recursively: true)
        
        return headNode
    }

head.scn 파일과 childNode를 만들어줍니다.

 

활용 예로 왼쪽 눈의 깜빡임에 따라 leftEye 노드의 z 스케일을 변경시켜보겠습니다. 

head.scn 파일을 열고 leftEye 노드의 Transforms를 확인합니다.

제가 활용한 에셋은 눈을 완전히 뜨고 있을 때 z 스케일이 1 이기때문에

blendShapes의 eyeBlinkLeft의 값을 반대로 활용하겠습니다.

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
	guard let faceAnchor = anchor as? ARFaceAnchor else { return }
    
    let blendShapes = faceAnchor.blendShapes
    if let eyeBlinkLeft = blendShapes[.eyeBlinkLeft] as? Float {
    	leftEyeNode?.scale.z = 1 - eyeBlinkLeft
    }
}

renderer - didUpdate 함수를 위와 같은 방식으로 구현하면 인식한 얼굴의 왼쪽 눈 깜빡임에 따른 blendShapes 값을 활용해 에셋을 실시간으로 변형할 수 있습니다.

 

참고자료 : https://developer.apple.com/documentation/arkit/arscnviewdelegate/