我一直试图在水平面上放置一个三维物体,但放置的3d物体没有固定在它的位置。
目前我可以将3d物体放置在水平面上,但放置三维物体在水平面上移动。放置的3d物体没有固定到它的位置。
这是我试图将3d对象放置在固定位置的代码:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
// gives us the location of where we touched on the 2D screen.
let touchLocation = touch.location(in: sceneView)
// hitTest is performed to get the 3D coordinates corresponding to the 2D coordinates that we got from touching the screen.
// That 3d coordinate will only be considered when it is on the existing plane that we detected.
let results = sceneView.hitTest(touchLocation, types: .existingPlaneUsingExtent)
// if we have got some results using the hitTest then do this.
if let hitResult = results.first {
let boxScene = SCNScene(named: "art.scnassets/porsche.scn")!
// var boxScene = SCNScene(named: "art.scnassets/porsche.scn")!
if let boxNode = boxScene.rootNode.childNode(withName: "car", recursively: true) {
print("box:::\(boxNode.childNodes)")
boxNode.position = SCNVector3(x: hitResult.worldTransform.columns.3.x, y: hitResult.worldTransform.columns.3.y, z: hitResult.worldTransform.columns.3.z)
// finally the box is added to the scene.
sceneView.scene.rootNode.addChildNode(boxNode)
}
}
}
}
以下是检测平面的代码:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
if anchor is ARPlaneAnchor {
anchors can be of many types, as we are just dealing with horizontal plane detection we need to downcast anchor to ARPlaneAnchor
let planeAnchor = anchor as! ARPlaneAnchor
creating a plane geometry with the help of dimentions we got using plane anchor.
let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z))
// a node is basically a position.
let planeNode = SCNNode()
setting the position of the plane geometry to the position we got using plane anchor.
planeNode.position = SCNVector3(x: planeAnchor.center.x, y: 0, z: planeAnchor.center.z)
// when a plane is created its created in xy plane instead of xz plane, so we need to rotate it along x axis.
planeNode.transform = SCNMatrix4MakeRotation(-Float.pi/2, 1, 0, 0)
//create a material object
let gridMaterial = SCNMaterial()
//setting the material as an image. A material can also be set to a color.
gridMaterial.diffuse.contents = UIImage(named: "art.scnassets/grid.png")
// assigning the material to the plane
plane.materials = [gridMaterial]
// assigning the position to the plane
planeNode.geometry = plane
//adding the plane node in our scene
node.addChildNode(planeNode)
}
else {
return
}
}
答案 0 :(得分:2)
我认为您需要为您的模型创建ARAnchor
:
无论何时放置虚拟对象,都要添加ARAnchor 表示其对ARSession的位置和方向。后 移动虚拟对象,删除旧位置的锚点 在新位置创建一个新锚点。添加锚告诉ARKit 一个位置很重要,提高世界跟踪质量 区域和帮助虚拟对象看起来相对于 现实世界的表面。
因此,这可能会指向正确的方向:
1st:创建一个引用你的boxNode的变量:
var boxNode: SCNNode?
第二名:在触摸位置创建ARAnchor
,例如:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//1. Get The Current Touch Location & Perform An ARSCNHitTest
guard let currentTouchLocation = touches.first?.location(in: sceneView),
let hitTest = sceneView.hitTest(currentTouchLocation, types: .existingPlaneUsingExtent).first else { return }
//2. Create An Anchor At The World Transform
let anchor = ARAnchor(transform: hitTest.worldTransform)
//3. Add It To The Scene
sceneView.add(anchor: anchor)
}
第3名:rendererDidAddNode delegate callback
初始化模型:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
//1. If We Havent Created Our Box Node Then Create It
if boxNode == nil{
//a. Check That Our SCNScene Is Valid
guard let validScene = SCNScene(named: "art.scnassets/porsche.scn"),
let carRoot = validScene.rootNode.childNode(withName: "car", recursively: true) else { return }
//b. Set The BoxNodes Position And Add It To The Anchor
boxNode = carRoot
boxNode?.position = SCNVector3(anchor.transform.columns.3.x, anchor.transform.columns.3.y, anchor.transform.columns.3.z)
node.addChildNode(boxNode!)
}
}
希望它有所帮助...