When an image is detected, I add a node in front of it.
The node is this picture and in relation to this picture I add other nodes, one above (1) of the picture and another next (2). Node 1 always gets in the correct position, but node 2 sometimes gets in front of the image, which is wrong, and sometimes gets in the right position that it's like the photo.
for anchor in sceneView.session.currentFrame!.anchors {
let imageAnchor = anchor as! ARImageAnchor
nodeInformation.position = SCNVector3Make(imageAnchor.transform.columns.3.x/100, imageAnchor.transform.columns.3.y/100 + 0.3, imageAnchor.transform.columns.3.z/100) //node 1
nodeAuthorInformation.position = SCNVector3Make(imageAnchor.transform.columns.3.x/100 + 0.3, imageAnchor.transform.columns.3.y/100, imageAnchor.transform.columns.3.z/100) //node 2
This is the code that I'm using to set the initial position of my two nodes.
So i would like to know how i can garantee that my second node will stay always in the right position, that it is next to picture.
How I add the nodes:
let tappedNode = self.sceneView.hitTest(gesture.location(in: gesture.view), options: [:])
if let result = tappedNode.first{
nodeInformation.transform = result.modelTransform
nodeAuthorInformation.transform = result.modelTransform
}
print("TAP PLACE = ", gesture.location(in: gesture.view))
if !tappedNode.isEmpty{
let node = tappedNode[0].node
print("NODE TAP = ", node.position)
let artPlane = SCNPlane(width: 0.3, height: 0.3)
artPlane.firstMaterial?.diffuse.contents = arArtDetailsScene
artPlane.firstMaterial?.isDoubleSided = true
let planeNode = SCNNode(geometry: artPlane)
planeNode.eulerAngles.x = .pi
authorPlane = SCNPlane(width: 0.2, height: 0.3)
authorPlane.firstMaterial?.diffuse.contents = arAuthorDetailsScene
authorPlane.firstMaterial?.isDoubleSided = true
let planeAuthorNode = SCNNode(geometry: authorPlane)
planeAuthorNode.eulerAngles.x = .pi
nodeInformation.addChildNode(planeNode)
nodeAuthorInformation.addChildNode(planeAuthorNode)
changeArtDetails(artId: artIndex + 1)
sceneView.scene.rootNode.addChildNode(nodeInformation)
sceneView.scene.rootNode.addChildNode(nodeAuthorInformation)
if sceneView.session.currentFrame != nil {
for anchor in sceneView.session.currentFrame!.anchors {
let imageAnchor = anchor as! ARImageAnchor
nodeInformation.position = SCNVector3Make(imageAnchor.transform.columns.3.x/100, imageAnchor.transform.columns.3.y/100 + 0.3, imageAnchor.transform.columns.3.z/100) // initial position node 1
nodeAuthorInformation.position = SCNVector3Make(imageAnchor.transform.columns.3.x/100 + 0.3, imageAnchor.transform.columns.3.y/100, imageAnchor.transform.columns.3.z/100) // initial position node 2
}
}
And I update the position of the node like this:
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
if sceneView.session.currentFrame != nil {
for anchor in sceneView.session.currentFrame!.anchors {
if let imageAnchor = anchor as? ARImageAnchor{
DispatchQueue.main.async {
self.nodeInformation.position = SCNVector3Make(imageAnchor.transform.columns.3.x/100, imageAnchor.transform.columns.3.y/100 + 0.3, imageAnchor.transform.columns.3.z/100)
self.nodeAuthorInformation.position = SCNVector3Make(self.nodeInformation.position.x + 0.3, self.nodeInformation.position.y - 0.3, self.nodeInformation.position.z)//SCNVector3Make(imageAnchor.transform.columns.3.x/100 + 0.3, imageAnchor.transform.columns.3.y/100, imageAnchor.transform.columns.3.z/100)
}
}
}
}
}
ARKit
updates position of anchors, not nodes. You will need to provide a node with three custom nodes as children in ARSCNViewDelegate.renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode?
if anchor is ARImageAnchor
instead of adding it manually to the scene.