我在理解SceneKit变换并将对象固定到检测到的面部时遇到了麻烦。我创建了一个面部检测应用程序,并成功应用了具有和不具有纹理的蒙版。我还成功地应用了由文本(“ 00”)制成的“眼镜”,包括遮挡节点。
在两种情况下,对象均按预期的方式与面部一起移动。但是,当我在ScendKit中创建由两个圆柱体制成的简单帽子时,其行为完全出乎意料。
首先,我似乎无法将帽子固定在脸上,但是不得不调整使帽子几乎每张脸都出现在不同位置的变换。更糟糕的是,帽子沿与面部相反的方向移动。向左旋转用户面部,帽子向右移动。将脸向上旋转,帽子向下移动。
很明显,我在这里缺少有关将对象锚定到脸部的重要信息。任何指导将不胜感激。
在iPhone X上运行的Xcode 10 beta 3,iOS 11.4.1。
有一个单独的帽子,眼镜和面具类:
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
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
答案 0 :(得分:3)
帽子的逼真度将取决于帽子相对于面部的位置以及它在场景中的显示效果(即帽子前面的特征应遮盖帽子本身) )。考虑到这一点,您将希望面部遮住帽子。因此,您的init
的{{1}}应该使用面几何来设置遮挡节点:
Hat
这将使面部出现在z深度大于面部网格的任何虚拟对象的前面。
您还需要将let occlusionNode: SCNNode
init(geometry: ARSCNFaceGeometry) {
/*
Taken directly from Apple's sample code https://developer.apple.com/documentation/arkit/creating_face_based_ar_experiences
*/
geometry.firstMaterial!.colorBufferWriteMask = []
occlusionNode = SCNNode(geometry: geometry)
occlusionNode.renderingOrder = -1
super.init()
addChildNode(occlusionNode)
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)
}
更改为let hatGeometry = ARSCNFaceGeometry(device: device)!
,否则可以通过眼睛看到帽子,从而产生令人讨厌的不良效果。
下一个问题是放置帽子的位置,使其看起来像在场景中一样。
因为我们希望脸部遮住帽子的大部分,所以最好将其直接放置在脸部几何形状顶部的y中。为了成功做到这一点,您可能希望帽子的枢轴点位于帽子几何形状的底部中心,并且在.scn文件中位于x = 0,y = 0处。例如,场景编辑器和节点检查器可能类似于:
然后在您的let hatGeometry = ARSCNFaceGeometry(device: device, fillMesh: true)!
中可以说
func update(withFaceAnchor anchor : ARFaceAnchor)
最后,对于帽子的z位置,您想要一个稍微为负的值,因为帽子的大部分位于人的脸后面。 func update(withFaceAnchor anchor : ARFaceAnchor) {
let faceGeometry = geometry as! ARSCNFaceGeometry
faceGeometry.update(from: anchor.geometry)
hat.position.y = faceGeometry.boundingSphere.radius
}
对我来说很好。