I'm having trouble understanding SceneKit transforms and anchoring an object to a detected face. I have created a face detection app and have successfully applied masks, with and without texture. I also successfully applied "glasses" made from text ( "00" ) including an occlusion node.
In both cases, the objects move with the face as expected. However, when I create a simple hat made from two cylinders within ScendKit the behavior is totally unexpected.
First, I could not seem to anchor the hat to the face, but had to adjust the transforms which made the hat appear in a different place with almost every face. Even worse, the hat moves in the opposite direction to the face. Rotate the user face to the left, the hat moves to the right. Rotate the face up, the hat moves down.
Clearly, I'm missing something important here about anchoring objects to the face. Any guidance would be appreciated.
Xcode 10 beta 3, iOS 11.4.1 running on an iPhone X.
There is a separate class for hat, glasses, mask:
class Hat : SCNNode {
init(geometry : ARSCNFaceGeometry) {
geometry.firstMaterial?.colorBufferWriteMask = []
super.init()
self.geometry = geometry
guard let url = Bundle.main.url(forResource: "hat", withExtension: "scn", subdirectory: "Models.scnassets") else {fatalError("missing hat resource")}
let node = SCNReferenceNode(url: url)!
node.load()
addChildNode(node)
}//init
func update(withFaceAnchor anchor : ARFaceAnchor) {
let faceGeometry = geometry as! ARSCNFaceGeometry
faceGeometry.update(from: anchor.geometry)
}//upadate
required init?(coder aDecoder: NSCoder) {
fatalError("(#function) has not been implemented")
}//r init
}//class
A couple of the functions in the ViewController:
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard let faceAnchor = anchor as? ARFaceAnchor else {return}
updateMessage(text: "Tracking your face")
switch contentTypeSelected {
case .none:
break
case .mask:
mask?.update(withFaceAnchor: faceAnchor)
case .glasses:
glasses?.update(withFaceAnchor: faceAnchor)
case .hat:
hat?.update(withFaceAnchor: faceAnchor)
}//switch
}//didUpdate
func createFaceGeometry() {
updateMessage(text: "Creating face geometry")
let device = sceneView.device!
let maskGeometry = ARSCNFaceGeometry(device: device)!
mask = Mask(geometry: maskGeometry, maskType : maskType)
let glassesGeometry = ARSCNFaceGeometry(device: device)!
glasses = Glasses(geometry: glassesGeometry)
let hatGeometry = ARSCNFaceGeometry(device: device)!
hat = Hat(geometry: hatGeometry)
}//createFaceGeometry





