今天要教大家怎麼跟 AR 的 3D 元件進行互動
在這邊,我們新增了手勢辨識在 ARSCNView,以便讓我們可以點擊螢幕和 AR 的 3D 元件進行互動
// 設定手勢辨識會觸發其他 func 的變數
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTap))
// 新增手勢到 ARSCNView
vARSCNView.addGestureRecognizer(tapGestureRecognizer)
@objc func didTap(recognizer: UIGestureRecognizer) {
// 取得點擊位置
let tapLocation = recognizer.location(in: vARSCNView)
// 將點擊的位置放進點擊測試變數
let hitTestResults = vARSCNView.hitTest(tapLocation)
//判斷點擊測試是否有點到 node(白色 Box)
guard let node = hitTestResults.first?.node else { return }
// 有的話就移除
node.removeFromParentNode()
}
結果看起來會是這樣子的:
請在 APP 中測試看看是否點擊到白色立方體會進行移除
extension float4x4 {
var translation: float3 {
let translation = self.columns.3
return float3(translation.x, translation.y, translation.z)
}
}
func addBox(x: Float = 0, y: Float = 0, z: Float = -0.2) {
// Float 1 = 1公尺,產生一個 寬:0.1、高:0.1、長:0.1 的
let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
// 新增一個叫 boxNode 的節點,代表位置與一物件在3D空間的座標
let boxNode = SCNNode()
boxNode.geometry = box
// 座標設定,這個位置和相機有關係,以正x軸:右邊、負x軸:左邊、正Y軸:上方、負Y軸:下方、正Z軸:往後、負Z軸:往前
boxNode.position = SCNVector3(x, y, z)
let scene = SCNScene()
scene.rootNode.addChildNode(boxNode)
vARSCNView.scene = scene
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTap))
vARSCNView.addGestureRecognizer(tapGestureRecognizer)
}
@objc func didTap(withGestureRecognizer recognizer: UIGestureRecognizer) {
let tapLocation = recognizer.location(in: vARSCNView)
let hitTestResults = vARSCNView.hitTest(tapLocation)
guard let node = hitTestResults.first?.node else {
// types參數要求hit test經由 AR 的相機圖像來搜尋真實世界的實體物或是表面。它內含許多類型,但本教學目前只針對特徵點
let hitTestResultsWithFeaturePoints = vARSCNView.hitTest(tapLocation, types: .featurePoint)
// 第一次hit test能成功移除,然後我們就將轉換矩陣類型 matrix_float4x4 到 float3 ,因為我們之前已增加了一個 extension 來完成此功能
if let hitTestResultWithFeaturePoints = hitTestResultsWithFeaturePoints.first {
let translation = hitTestResultWithFeaturePoints.worldTransform.translation
在一特徵點上輸入x, y和z來加入一個立方體
addBox(x: translation.x, y: translation.y, z: translation.z)
}
return
}
node.removeFromParentNode()
}