问题
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