Как узнать, недоступна ли поверхность, обнаруженная ARKit?
Я работаю над приложением с фреймворками ARKit и SceneKit. В моем приложении я включил обнаружение поверхности (я следовал за образцом размещения объектов, предоставленным Apple). Как определить, что обнаруженная поверхность больше не доступна? То есть изначально только если пользователь обнаружил поверхность в ARSession, я разрешаю ему разместить 3D-объект.
Но если пользователь быстро перемещается или фокусируется где-то, обнаруженная площадь поверхности теряется. В этом случае, если пользователь пытается разместить другой объект, я не должен позволять ему размещать его, пока он снова не отсканирует пол и не исправит поверхность.
Есть ли какой-нибудь делегат, который может сообщить нам, что обнаруженная поверхность больше не доступна?
2 ответа
Есть функции делегата, которые вы можете использовать. Делегат является ARSCNViewDelegate
У него есть функция, которая renderer(_:didRemove:for:)
Это срабатывает, когда ARAnchor был удален. Вы можете использовать эту функцию для выполнения некоторых операций при удалении поверхности.
Есть два способа "потерять" поверхность, поэтому существует несколько подходов к решению такой проблемы.
Как отмечено в другом ответе, есть ARSCNViewDelegate
метод, который вызывает ARKit, когда якорь удаляется из сеанса AR. Тем не менее, ARKit не удаляет привязки самолета во время сеанса работы - как только он обнаружил самолет, он предполагает, что самолет всегда там. Так что этот метод вызывается только если:
- Вы удаляете якорь самолета, передавая его
session.remove(anchor:)
, или же - Вы сбрасываете сеанс, запустив его снова с
.removeExistingAnchors
вариант.
Я не уверен, что первое - хорошая идея, но со вторым важно справиться, поэтому вы, вероятно, хотите, чтобы ваш делегат справился с этим хорошо.
Вы также можете "потерять" поверхность, пропустив ее из поля зрения - например, ARKit обнаруживает стол, а затем пользователь поворачивается, чтобы камера больше не была направлена на стол или рядом с ним.
Сам ARKit не предлагает никакой помощи для решения этой проблемы. Тем не менее, он дает вам всю информацию, необходимую для математики. Вы получите положение, ориентацию и размер привязки плоскости, чтобы вы могли рассчитать четыре ее угловых точки. И вы получаете матрицу проекции камеры, так что вы можете проверить, есть ли какая-либо точка в усечении просмотра.
Так как вы уже используете SceneKit, есть также способы заставить SceneKit сделать математику за вас... Работа в обратном направлении:
- SceneKit дает вам
isNode(_:insideFrustumOf:)
тест, так что если у вас естьSCNNode
чья ограничительная рамка соответствует размеру вашей плоскости привязки, вы можете передать это вместе с камерой (view.pointOfView
) чтобы узнать, виден ли узел. - Чтобы получить узел, ограничивающий прямоугольник которого совпадает с привязкой к плоскости, реализуйте
ARSCNViewDelegate
didAdd
а такжеdidUpdate
обратные вызовы для создания / обновленияSCNPlane
чье положение и размеры соответствуютARPlaneAnchor
Центр и степень. (Не забудьте перевернуть самолет в сторону, так какSCNPlane
по умолчанию вертикально ориентирован.) - Если вы не хотите, чтобы эта плоскость была видна в представлении AR, установите ее материалы прозрачными.