gpt4 book ai didi

swift - 如何找到在 HitTest 中找到的平面中心 ARKit SceneKit

转载 作者:行者123 更新时间:2023-11-28 13:24:53 26 4
gpt4 key购买 nike

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

@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
}

最佳答案

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

将平面添加到场景后,您只需将新几何体添加为该节点的子节点即可。

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

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()
}

}

关于swift - 如何找到在 HitTest 中找到的平面中心 ARKit SceneKit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58564321/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com