Reputation: 1823
I am working on an application with ARKit and SceneKit frameworks. In my application I have enabled surface detection (I followed the placing objects sample provided by Apple). How to find if the surface detected is no more available? That is, initially only if user has detected the surface in ARSession I am allowing him to place the 3D object.
But if the user moves rapidly or focuses somewhere, the detected surface area is getting lost. In this case if the user tries to place another object I shouldn't allow him to place it until he scans the floor again and get the surface corrected.
Is there any delegate which is available to let us know that the surface detected is no more available?
Upvotes: 1
Views: 2339
Reputation: 126177
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:
session.remove(anchor:)
, or.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:
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.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.)Upvotes: 2
Reputation: 1142
There are delegate functions that you can use. The delegate is the ARSCNViewDelegate
It has a function that is renderer(_:didRemove:for:)
that fires when an ARAnchor has been removed. You can use this function to perform some operation when a surface gets removed.
Upvotes: 3