【问题标题】:how to find centre of a plane found in a hit test ARKit SceneKit如何在命中测试 ARKit SceneKit 中找到飞机的中心
【发布时间】:2019-10-26 07:31:59
【问题描述】:

在图像检测应用程序中,图像被识别,然后创建一个不透明的覆盖平面,因此当用户点击屏幕时,命中测试会找到覆盖平面,并且可以创建一个新对象。但我想将对象准确定位在底层图像的中心。我怎样才能让它始终位于图像/平面的中心,并具有相同的方向。这可以从命中测试结果中得到吗?感谢您的建议!

@objc func handleScreenTap(sender: UITapGestureRecognizer) {
  let tappedSceneView = sender.view as! ARSCNView
  let tapLocation = sender.location(in: tappedSceneView)

  let planeIntersections = tappedSceneView.hitTest(tapLocation, types: [.estimatedHorizontalPlane, .estimatedVerticalPlane])
  if !planeIntersections.isEmpty {
    addSceneAtPositionOnPlane(hitTestResult: planeIntersections.first!)
}

func addSceneAtPositionOnPlane(hitTestResult: ARHitTestResult) {

  let transform = hitTestResult.worldTransform
  let positionColumn = transform.columns.3
  let initialPosition = SCNVector3(positionColumn.x,
                                 positionColumn.y,
                                 positionColumn.z)

   let node = self.createScene(for: initialPosition)
   sceneView.scene.rootNode.addChildNode(node)
}

func createScene(for position: SCNVector3) -> SCNNode {

  let box = SCNNode(geometry: SCNBox(width: 0.1, //x
                                    height: 0.1, //y
                                    length: 0.1, //z
                                    chamferRadius: 0))

  box.geometry?.firstMaterial?.diffuse.contents = UIColor.red
  box.geometry?.firstMaterial?.isDoubleSided = true
  box.opacity = 0.8

  box.position = position        
  return box
}

【问题讨论】:

    标签: swift scenekit arkit


    【解决方案1】:

    如果您已经添加了一个 SCNNode 来在检测到的图像之上渲染一个平面,那么您可以只使用返回 SceneKit 节点的 SceneKit hitTest 方法,而不是尝试针对 ARKit 几何体进行命中测试。

    一旦您将平面添加到场景中,您就可以将新几何图形添加为该节点的子节点。

    这是一个示例,一旦检测到图像,就会在其顶部绘制一个平面,然后当用户单击该平面时,会添加一个框作为子项,然后该框将跟随跟踪的图像并具有正确的位置和方向。

    import UIKit
    import SceneKit
    import ARKit
    
    class ViewController: UIViewController, ARSCNViewDelegate {
    
      @IBOutlet var sceneView: ARSCNView!
    
      override func viewDidLoad() {
        super.viewDidLoad()
    
        sceneView.delegate = self
    
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(onTap))
        sceneView.addGestureRecognizer(tapGesture)
      }
    
      @objc func onTap(_ recognizer: UITapGestureRecognizer) {
        let point = recognizer.location(in: sceneView)
    
        guard let hit = sceneView.hitTest(point, options: nil).first else {
          return
        }
    
        let box = SCNBox(width: 0.02, height: 0.02, length: 0.02, chamferRadius: 0)
        let node = SCNNode(geometry: box)
        node.position = SCNVector3(0, 0, 0.01)
        box.materials.first?.diffuse.contents = UIColor.red
        hit.node.addChildNode(node)
      }
    
      override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    
        let configuration = ARWorldTrackingConfiguration()
    
        guard let images = ARReferenceImage.referenceImages(inGroupNamed: "ARTest", bundle: nil) else {
          return
        }
    
        configuration.detectionImages = images
        configuration.maximumNumberOfTrackedImages = 1
        sceneView.session.run(configuration)
      }
    
      func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard let imageAnchor = anchor as? ARImageAnchor else {
          return
        }
    
        let size = imageAnchor.referenceImage.physicalSize
        let plane = SCNPlane(width: size.width, height: size.height)
        let planeNode = SCNNode(geometry: plane)
        planeNode.eulerAngles.x = -Float.pi / 2
        planeNode.opacity = 0.9
        node.addChildNode(planeNode)
      }
    
      override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        sceneView.session.pause()
      }
    
    }
    
    

    【讨论】:

    • hi Mark - 将拾取用户点击的平面上的点或其下方的平面/图像的确切中心?
    • 此示例将在平面中心添加框。您需要确保在 AR 资源组中的图像上设置了准确的宽度/高度。
    • 我必须在渲染器 didAdd 节点的 addChildNode 之后添加 self.sceneView.session.setWorldOrigin(relativeTransform: imageAnchor.transform)。或者盒子是在 AR 会话开始时在原点创建的
    • 能从hitTest中得到飞机的尺寸吗?
    猜你喜欢
    • 2018-02-22
    • 2018-02-15
    • 2015-06-14
    • 2016-02-02
    • 2018-01-08
    • 2018-04-22
    • 1970-01-01
    • 1970-01-01
    • 2019-10-25
    相关资源
    最近更新 更多