When application launched first a vertical surface is detected on one wall than camera focus to the second wall, in the second wall another surface is detected. T
The clue to the answer is in the beginning line of your if let
statement.
Lets break this down:
When you say let anchor = sceneView.session.currentFrame?.anchors.first
, you are referencing an optional array of ARAnchor
, which naturally can have more than one element.
Since your are always calling first
e.g. index [0], you will always get the 1st ARAnchor
which was added to the array.
Since you now have 2 anchors, you would naturally need the last (latest) element. As such you can try this as a starter:
if let anchor = sceneView.session.currentFrame?.anchors.last {
let node = sceneView.node(for: anchor)
addNode(position: SCNVector3Zero, anchorNode: node)
} else {
debugPrint("anchor node is nil")
}
Update: Since another poster has interpreted the question differently, in that they believe the question is how can I detect if an ARPlaneAnchor is in view? Let's approach it another way.
First we need to take into consideration that the ARCamera has a Frostrum in which our content is shown:
As such, we would then need to determine whether an ARPlaneAnchor was inViewOfFrostrum
.
First we will create 2 variables:
var planesDetected = [ARPlaneAnchor: SCNNode]()
var planeID: Int = 0
The 1st to store the ARPlaneAnchor
and its associated SCNNode
, and the 2nd in order to provide a unique ID for each plane.
In the ARSCNViewDelegate
we can visualise an ARPlaneAnchor and then store it's information e.g:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
//1. Get The Current ARPlaneAnchor
guard let anchor = anchor as? ARPlaneAnchor else { return }
//2. Create An SCNode & Geometry To Visualize The Plane
let planeNode = SCNNode()
let planeGeometry = SCNPlane(width: CGFloat(anchor.extent.x), height: CGFloat(anchor.extent.z))
planeGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
planeNode.geometry = planeGeometry
//3. Set The Position Based On The Anchors Extent & Rotate It
planeNode.position = SCNVector3(anchor.center.x, anchor.center.y, anchor.center.z)
planeNode.eulerAngles.x = -.pi / 2
//4. Add The PlaneNode To The Node & Give It A Unique ID
node.addChildNode(planeNode)
planeNode.name = String(planeID)
//5. Store The Anchor & Node
planesDetected[anchor] = planeNode
//6. Increment The Plane ID
planeID += 1
}
Now we have stored the detected planes, we then of course need to determine if any of these are in view of the ARCamera e.g:
/// Detects If An Object Is In View Of The Camera Frostrum
func detectPlaneInFrostrumOfCamera(){
//1. Get The Current Point Of View
if let currentPointOfView = augmentedRealityView.pointOfView{
//2. Loop Through All The Detected Planes
for anchorKey in planesDetected{
let anchor = anchorKey.value
if augmentedRealityView.isNode(anchor, insideFrustumOf: currentPointOfView){
print("ARPlaneAnchor With ID \(anchor.name!) Is In View")
}else{
print("ARPlaneAnchor With ID \(anchor.name!) Is Not In View")
}
}
}
}
Finally we then need to access this function which we could do in the following delegate
method for example renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval)
:
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
detectPlaneInFrostrumOfCamera()
}
Hopefully both of these will point in the right direction...