Я сейчас работаю над приложением ARKit.Он должен иметь возможность размещать различные трехмерные объекты, перемещать их и сохранять карту мира.размещение и перемещение различных объектов не проблема, если я не использую якоря.Как только я ставлю якоря, чтобы сохранить карту мира, я не могу правильно перемещать объекты.Я использовал Apple Dev Project Взаимодействие с 3d-объектами как идею.Они удалили якорь, когда начали перемещать объект, и добавили новый.Но так как у меня есть разные объекты, это не работает должным образом.Когда пользователь нажимает кнопку добавления, он выбирает, какие объекты он хотел бы разместить.Это устанавливает название модели на правильную модель.Когда он нажимает на экран, он ставит якорь с именем модели.В рендерере (didAdd) будет создан правильный узел.Функция перемещения заменяет модель и привязку, но она не работает (вылетает при перезагрузке).Я думаю, что проблема в том, чтобы не допустить нулевых якорей, но я не нашел хорошего способа сделать это.
Можете ли вы мне помочь?
@objc func tapped(sender: UITapGestureRecognizer){
let sceneView = sender.view as! ARSCNView
let tapLocation = sender.location(in: sceneView)
let hitTest = sceneView.hitTest(tapLocation, types: .existingPlaneUsingExtent)
if !hitTest.isEmpty{
print("Touched on the plane")
let hitTestResult = hitTest.first!
anchor = ARAnchor(name: "\(modelName)", transform: hitTestResult.worldTransform)
print ("Anchor Name: , \(anchor!.name)" )
self.sceneView.session.add(anchor: anchor!)
}else{
print("Not a plane")}
}
@objc func moveNode(_ gesture: UIPanGestureRecognizer) {
//1. Get The Current Touch Point
let currentTouchPoint = gesture.location(in: sceneView)
//2. If The Gesture State Has Begun Perform A Hit Test To Get The SCNNode At The Touch Location
if gesture.state == .began{
//2a. Perform An SCNHitTest To Detect If An SCNNode Has Been Touched
guard let nodeHitTest = sceneView.hitTest(currentTouchPoint, options: nil).first else { return }
//2b. Get The SCNNode Result
let nodeHit = nodeHitTest.node
//2c. Set As The Current Node
selectedNode = nodeHit
//if anchor is not nil remove from session
}
//3. If The Gesture State Has Changed Then Perform An ARSCNHitTest To Detect Any Existing Planes
if gesture.state == .changed{
//3b. Get The Next Feature Point Etc
guard let hitTest = sceneView.hitTest(currentTouchPoint, types: .existingPlane).first else { return }
//3c. Convert To World Coordinates
let worldTransform = hitTest.worldTransform
//3d. Set The New Position
let newPosition = SCNVector3(worldTransform.columns.3.x, worldTransform.columns.3.y, worldTransform.columns.3.z)
//3e. Apply To The Node
selectedNode?.simdPosition = float3(newPosition.x, newPosition.y, newPosition.z)
}
//4. If The Gesture State Has Ended Remove The Reference To The Current Node
if gesture.state == .ended{
let selectedAnchor = sceneView.anchor(for: selectedNode!)
if( selectedAnchor == nil){
return
}
sceneView.session.remove(anchor: selectedAnchor!)
guard let hitTest = sceneView.hitTest(currentTouchPoint, types: .existingPlane).first else { return }
//3c. Convert To World Coordinates
selectedNodeName = getParent(selectedNode)?.name
let worldTransform = hitTest.worldTransform
let newAnchor = ARAnchor(name: "\(selectedNodeName)", transform: worldTransform)
print("NewAnchorName: , \(newAnchor.name)")
sceneView.session.add(anchor: newAnchor)
selectedNode = nil
selectedNodeName = nil
print("NewAnchorNameAfterNil: , \(newAnchor.name)")
//adOrUpdateAnchor
}
}