ARKit 将节点放置在手指按下的位置

ARKit place node where finger press is

我正在使用 ARKit 开发一个 ios 应用程序,我想知道如何在我将手指按在屏幕上但距离屏幕大约 0.5m 的位置创建一个节点。我知道我必须考虑设备的方向,但我仍然很困惑从哪里开始。任何帮助都会很棒!谢谢。

从一些不需要 ARKit 的简单解决方案开始:

var scnV : SCNView!
var scnN = SCNNode()
var depthForZ = 0.50

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch01   = touches.first!
    let t_Point   = touch01.location(in: scnV)
    scnN.position = scnV.unprojectPoint(SCNVector3(x:Float(t_Point.x), y:Float(t_Point.y), z:depthForZ))
}

如果需要 ARKit,您可以在代码中的某处继续:

    var trans = matrix_identity_float4x4
    trans.columns.3.x = Float(t_Point.x)
    trans.columns.3.y = Float(t_Point.y)
    trans.columns.3.z = depthForZ
    let transForA = simd_mul(scN.transform, trans)

    let newA = ARAnchor(transform: transForA)
    scnV.session.add(anchor: newA)

或者用之前的 transForA 结构更新 ARSession 创建的 SCNNode 的转换

我希望这能帮助你开始一个基本的项目

解决方法很简单。

将您需要的节点作为子节点添加到位置向量为 (0,0,1) 的相机。 现在,保存您创建的那个节点的世界位置,并立即从相机中删除子节点。

再次将您的节点添加为具有已保存世界位置的根节点的子节点。

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

    let boxNode = SCNNode.init()
    let boxGeometry = SCNBox.init(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
    boxGeometry.materials.first?.diffuse.contents = UIColor.red
    boxNode.geometry = boxGeometry
    boxNode.position = SCNVector3.init(0, 0, -0.5)
    self.sceneView.pointOfView?.addChildNode(boxNode)


    let boxPosition = boxNode.worldPosition
    boxNode.removeFromParentNode()
    boxNode.worldPosition = boxPosition
    self.sceneView.scene.rootNode.addChildNode(boxNode)

}

编辑:

解决方案需要稍作修改。 要获得世界位置,请在相机前创建一个 planeNode(不需要时可以将其删除)。并在 sceneView 上执行 hitTestResult 以获取 worldPosition。

    let planeGeometry = SCNPlane.init(width: 10, height: 10)
    planeGeometry.materials.first?.transparency = 0
    planeNode.geometry = planeGeometry
    planeNode.position = SCNVector3.init(0, 0, -1)
    planeNode.name = "HitTestPlane"
    self.sceneView.pointOfView?.addChildNode(planeNode)



    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {


    let loc = touches.first?.location(in: self.sceneView)
    let hitTextResult = self.sceneView.hitTest(loc!, options: [:])

    for result in hitTextResult {
        if result.node.name == "HitTestPlane" {

            let hitPosition = SCNVector3.init(result.worldCoordinates.x, result.worldCoordinates.y, result.worldCoordinates.z)
            let boxNode = SCNNode.init()
            let boxGeometry = SCNBox.init(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
            boxGeometry.materials.first?.diffuse.contents = UIColor.red
            boxNode.geometry = boxGeometry

            boxNode.position = hitPosition
            self.sceneView.scene.rootNode.addChildNode(boxNode)

        }
    }

}