我已经用SceneView会话设置了ARFaceTrackingConfiguration,并在场景资产中创建了一个虚拟的3D模型。
模型是在sceneView中导入的,但是随着相机的移动,它会相应地移动,我需要的是修复模型在sceneView中心的位置。
下面的图片展示了我正在努力实现的目标。
因此,3D模型不应该基于摄像机的运动而移动。

@IBOutlet var sceneView: ARSCNView!
let scene = SCNScene(named: "art.scnassets/TEST.scn")!
var contentNode: SCNNode?
override func viewDidLoad() {
super.viewDidLoad()
// Set the view's delegate
sceneView.delegate = self
// Show statistics such as fps and timing information
sceneView.showsStatistics = true
sceneView.scene = self.scene
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Create a session configuration
let configuration = ARFaceTrackingConfiguration()
configuration.isLightEstimationEnabled = true
// 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()
}
// MARK: - ARSCNViewDelegate
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
guard let faceAnchor = anchor as? ARFaceAnchor else { return nil }
let faceGeometry = ARSCNFaceGeometry(device: sceneView.device!)!
self.contentNode = SCNNode(geometry: faceGeometry)
return self.contentNode
}发布于 2019-05-02 20:11:30
这是我自己问题的答案。
首先,要静态地将一个对象放置在sceneView的中间,这意味着当摄像机移动时,您不希望对象移动,您需要将它的位置设置为摄像机当前面对的位置。要获得摄像机的当前位置,我们需要访问pointOfView值。pointOfView包含cameraView的当前位置和方向,一个用例是当我们需要在摄像机前面添加节点时。位置和方向在pointOfView内部编码为transformMatrices SCNMatrix4。来自苹果公司的文档:
下图显示了您可以进行的一些更常见的转换的矩阵配置。将任意坐标乘以恒等变换返回完全相同的坐标。对于其他转换,如何修改坐标完全取决于您更改的矩阵组件。例如,为了仅沿x轴进行转换,您将为转换矩阵的tx组件提供一个非零值,并将ty和tz值保留为0。对于旋转,您将提供适当的正弦和余弦值的目标旋转角度。矩阵配置

菲尤!现在,获取类体中的pointOfView,而不是在ARSCNViewDelegate方法中,如果您在renderer(_nodeFor:)方法中这样做,那么您的对象将遵循面几何图形:
guard let pointOfView = self.sceneView.pointOfView else { return }然后,您可以通过以下方法将对象定位在屏幕的中间:
DispatchQueue.main.async {
pointOfView.addChildNode(yourNode)
}因此,现在物体的中心是在摄像机前面,它将不会相应地移动与相机的运动。
然后,为了通过上下倾斜来移动对象,我们需要实现ARSCNViewDelegate并调用:
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode?该方法要求委托提供一个与新添加的锚点相对应的SceneKit节点,在我的场景中,我对FaceAnchor感兴趣。我为faceAnchor分配了一个具有0透明度的人脸几何,因为我不需要通过该节点跟踪人脸位置--这仅仅是为了跟踪面部位置,当人脸被移动时,didUpdate方法将被调用,然后我们可以更新节点或didUpdate方法中的任何东西,因为每当移动目标节点时,都会调用它。
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard let faceAnchor = anchor as? ARFaceAnchor else { return }
let faceTransform = faceAnchor.transform
let positionY = faceLocation.columns.2.y
let positionX = faceLocation.columns.2.x
let horizentalLine = Int(positionY * 100)
self.horizentalNode.eulerAngles = SCNVector3(horizentalLine.degreeToRadians, 0, 0)因此,正如我前面说过的,在每个节点/锚内部都有一个名为transform的属性,它是一个矩阵,编码锚相对于AR会话的世界坐标空间的位置、方向和规模。简而言之:这与三维度量有关。如果发现第2列中的y和x值是头部的水平和垂直运动,则这里的小数学+ degreeToRadians扩展就是转换eulerAngles旋转矩阵的值。
https://stackoverflow.com/questions/55906182
复制相似问题