There are two ways to “lose” a surface, so there’s more than one approach to dealing with such a problem.
As noted in the other answer, there’s an ARSCNViewDelegate
method that ARKit calls when an anchor is removed from the AR session. However, ARKit doesn’t remove plane anchors during a running session — once it’s detected a plane, it assumes the plane is always there. So that method gets called only if:
- You remove the plane anchor directly by passing it to
session.remove(anchor:)
, or
- You reset the session by running it again with the
.removeExistingAnchors
option.
I’m not sure the former is a good idea, but the latter is important to handle, so you probably want your delegate to handle it well.
You can also “lose” a surface by having it pass out of view — for example, ARKit detects a table, and then the user turns around so the camera isn’t pointed at or near the table anymore.
ARKit itself doesn’t offer you any help for dealing with this problem. It gives you all the info you need to do the math yourself, though. You get the plane anchor’s position, orientation, and size, so you can calculate its four corner points. And you get the camera’s projection matrix, so you can check for whether any point is in the viewing frustum.
Since you’re already using SceneKit, though, there are also ways to get SceneKit to do the math for you... Working backwards:
- SceneKit gives you an
isNode(_:insideFrustumOf:)
test, so if you have a SCNNode
whose bounding box matches the extent of your plane anchor, you can pass that along with the camera (view.pointOfView
) to find out if the node is visible.
- To get a node whose bounding box matches a plane anchor, implement the
ARSCNViewDelegate
didAdd
and didUpdate
callbacks to create/update an SCNPlane
whose position and dimensions match the ARPlaneAnchor
’s center and extent. (Don’t forget to flip the plane sideways, since SCNPlane
is vertically oriented by default.)
- If you don’t want that plane visible in the AR view, set its materials to be transparent.