emm*_*a93 2 xcode scenekit swift xcode9-beta arkit
我正在玩ARKit和图像检测。现在,我有一个可检测图像的应用程序,可将屏幕上的平面放置在检测到的对象所在的位置。
如何在飞机上添加可点击元素,例如按钮。我想对每个检测到的对象都有一个click事件。
这是我的渲染器函数的外观:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let imageAnchor = anchor as? ARImageAnchor else { return }
let referenceImage = imageAnchor.referenceImage
updateQueue.async {
let plane = SCNPlane(width: referenceImage.physicalSize.width,
height: referenceImage.physicalSize.height)
let planeNode = SCNNode(geometry: plane)
planeNode.opacity = 0.25
planeNode.eulerAngles.x = -.pi / 2
planeNode.runAction(self.imageHighlightAction)
node.addChildNode(planeNode)
}
DispatchQueue.main.async {
let imageName = referenceImage.name ?? ""
self.statusViewController.cancelAllScheduledMessages()
// self.statusViewController.showMessage("Detected image “\(imageName)”")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let second = storyboard.instantiateViewController(withIdentifier: "InfoViewController")as! InfoViewController
second.myStringValue = imageName
// self.navigationController?.pushViewController(second, animated: true)
}
}
Run Code Online (Sandbox Code Playgroud)
有几种方法可以解决此问题:
1:标准方法:
在您的delegate方法中,按照以下方式为每个节点分配一个名称(显然,如果您有很多节点,则需要根据需要将它们存储在数组或字典中):
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
//1. Check We Have The Image Anchor
guard let imageAnchor = anchor as? ARImageAnchor else { return }
//2. Get The Reference Image
let referenceImage = imageAnchor.referenceImage
//1. Create The Plane Geometry With Our Width & Height Parameters
let planeGeometry = SCNPlane(width: referenceImage.physicalSize.width,
height: referenceImage.physicalSize.height)
//2. Create A New Material
let material = SCNMaterial()
material.diffuse.contents = UIColor.red
//3. Create The Plane Node
let planeNode = SCNNode(geometry: planeGeometry)
planeNode.geometry?.firstMaterial = material
planeNode.opacity = 0.25
planeNode.eulerAngles.x = -.pi / 2
//4. Add A Name To The Node
planeNode.name = "I Was Clicked"
//5. Add It To The Scene
node.addChildNode(planeNode)
}
Run Code Online (Sandbox Code Playgroud)
然后使用touchesBegan,执行一次hitTest并相应地处理触摸:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
/*
1. Get The Current Touch Location
2. Check That We Have Touched A Valid Node
3. Check If The Node Has A Name
4. Handle The Touch
*/
guard let touchLocation = touches.first?.location(in: augmentedRealityView),
let hitNode = augmentedRealityView?.hitTest(touchLocation, options: nil).first?.node,
let nodeName = hitNode.name
else {
//No Node Has Been Tapped
return
}
//Handle Event Here e.g. PerformSegue
print(nodeName)
}
Run Code Online (Sandbox Code Playgroud)
2:一种有趣的方法:
UIKit元素实际上可以作为添加SCNGeometry's Material。我个人没有见过很多人使用这种方法,但是对于想与结合UIKit使用的人来说,它可能会有用ARKit。
创建一个自定义UIButton,例如:
/// Clickable View
class ClickableView: UIButton{
override init(frame: CGRect) {
super.init(frame: frame)
self.addTarget(self, action: #selector(objectTapped(_:)), for: .touchUpInside)
self.backgroundColor = .red
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
/// Detects Which Object Was Tapped
///
/// - Parameter sender: UIButton
@objc func objectTapped(_ sender: UIButton){
print("Object With Tag \(tag)")
}
}
Run Code Online (Sandbox Code Playgroud)
然后在您的委托方法中执行以下操作:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
//1. Check We Have The Image Anchor
guard let imageAnchor = anchor as? ARImageAnchor else { return }
//2. Get The Reference Image
let referenceImage = imageAnchor.referenceImage
//1. Create The Plane Geometry With Our Width & Height Parameters
let planeGeometry = SCNPlane(width: referenceImage.physicalSize.width,
height: referenceImage.physicalSize.height)
//2. Create A New Material
let material = SCNMaterial()
DispatchQueue.main.async {
//3. Create The New Clickable View
let clickableElement = ClickableView(frame: CGRect(x: 0, y: 0,
width: 300,
height: 300))
clickableElement.tag = 1
//4. Add The Clickable View As A Materil
material.diffuse.contents = clickableElement
}
//5. Create The Plane Node
let planeNode = SCNNode(geometry: planeGeometry)
planeNode.geometry?.firstMaterial = material
planeNode.opacity = 0.25
planeNode.eulerAngles.x = -.pi / 2
//6. Add It To The Scene
node.addChildNode(planeNode)
}
Run Code Online (Sandbox Code Playgroud)
这应该让您开始...
| 归档时间: |
|
| 查看次数: |
2533 次 |
| 最近记录: |