手指按下的ARKit放置节点

时间:2018-06-22 16:53:45

标签: ios swift scenekit arkit

我正在使用ARKit开发一个ios应用程序,我想知道如何在我的手指按屏幕的确切位置(距屏幕约0.5m)创建一个节点。我知道我将不得不考虑设备的方向,但是对于从何处开始我仍然很困惑。任何帮助将是巨大的!谢谢。

2 个答案:

答案 0 :(得分:1)

解决方案很简单。

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

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

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)

        }
    }

}

答案 1 :(得分:0)

从一些简单的解决方案开始,就不需要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的变换

我希望这可以帮助您从一个基础项目开始