我目前正在开发ARKit应用。它应该能够放置不同的3d对象,将它们四处移动并保存世界地图。只要我不使用锚点,就可以放置和移动不同的对象。一旦放置锚点以保存世界地图,我就无法正确移动对象。我使用苹果开发人员项目“与3d对象交互”作为想法。他们开始移动物体时移开了锚,然后又添加了一个新物体。但是由于我有不同种类的对象,因此无法正常工作。当用户点击添加按钮时,他选择他想放置的对象。这会将模型名称设置为正确的模型。当他在屏幕上点击时,它会将锚与modelName一起放置。在renderer(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
}
}