ARKit place node where finger press is

谁说我不能喝 提交于 2021-01-25 07:23:18

问题


I am working on an ios app with ARKit and I am wondering how to create a node exactly where I press my finger on the screen but approximately 0.5m into the screen. I know I will have to take into account the orientation of the device but I am still very confused on where to begin. Any help would be great! Thanks.


回答1:


The solution is simple.

Add a your required node as a child node to the camera with position vector (0,0,1). Now, save the world position of that node you created and immediately remove the child node from the camera.

Add your node again as the child of the rootNode with the saved world position.

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)

}

Edit:

The solution will need a small modification. To get the world position, create a planeNode before your camera (you may remove it when not required). And do a hitTestResult on the sceneView to fetch the 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)

        }
    }

}



回答2:


To start with some simple solution there is no need for 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))
}

If ARKit is needed you can continue somewhere in your code with:

    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)

Or instead update the transform of a SCNNode created by ARSession with the previous transForA structure

I hope that helps you to begin with a basic project



来源:https://stackoverflow.com/questions/50992492/arkit-place-node-where-finger-press-is

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!