Ответ 1
Обновление: Как и в iOS 11.3 (также известный как "ARKit 1.5" ), существует разница между добавлением ARAnchor
к сеансу (а затем связыванием содержимого SceneKit с ним через обратные вызовы ARSCNViewDelegate
) и просто размещение контента в пространстве SceneKit.
Когда вы добавляете привязку к сеансу, вы сообщаете ARKit, что определенная точка в мировом пространстве имеет отношение к вашему приложению. Затем ARKit может выполнить некоторую дополнительную работу, чтобы убедиться, что ее мировое координатное пространство точно соответствует реальному миру, по крайней мере, в непосредственной близости от этой точки.
Итак, если вы пытаетесь сделать виртуальный контент "привязанным" к какой-то реальной точке интереса, например, положить объект на стол или стену, вы должны увидеть меньше "дрифта" из-за неточности во всем мире если вы придаете этому объекту якорь, чем если бы вы разместили его в пространстве SceneKit. И если этот объект перемещается из одного статического положения в другое, вы захотите удалить исходный якорь и добавить его в новую позицию позже.
Кроме того, в iOS 11.3 вы можете выбрать в для "релокализации" - процесс, который помогает ARKit возобновить сеанс после его прерывания ( по телефону, переключению приложений и т.д.). Сеанс все еще работает, когда он пытается выяснить, как сопоставить то, где вы были раньше, до того места, где вы сейчас находитесь, что может привести к изменению позиций якорей в мировом пространстве после успешной релокализации.
(С другой стороны, если вы просто создаете космических захватчиков, которые плавают в воздухе, совершенно соответствующее мировое пространство не так важно, и, таким образом, вы не увидите большой разницы между якорной и не- позиционирование с привязкой.)
См. бит вокруг "Использовать привязки для улучшения качества отслеживания вокруг виртуальных объектов" в Apple Обработка 3D-взаимодействия и элементов управления пользовательским интерфейсом в расширенной реальности/пример кода.
Остальная часть этого ответа остается исторически актуальной для iOS 11.0-11.2.5 и объясняет некоторый контекст, поэтому я оставлю его ниже...
Сначала рассмотрим использование ARAnchor
без SceneKit.
-
Если вы используете
ARSKView
, вам нужен способ ссылки на позиции/ориентации в 3D (реальном) пространстве, потому что SpriteKit не является 3D. Вам нужноARAnchor
отслеживать позиции в 3D, чтобы они могли отображаться в 2D. -
Если вы создаете свой собственный движок с помощью Metal (или GL, по какой-то странной причине)... это не API описания 3D-сцены - это API программирования GPU, поэтому на самом деле он не имеет понятие мирового пространства. Вы можете использовать
ARAnchor
как мост между понятием ARKit о мировом пространстве и тем, что вы строите.
Поэтому в некоторых случаях вам нужно ARAnchor
, потому что это единственный разумный способ ссылаться на 3D-позиции. (И, конечно, если вы используете определение плоскости, вам нужно ARPlaneAnchor
, потому что ARKit фактически переместит их относительно пространства сцены, поскольку он уточнит свои оценки того, где находятся плоскости.)
С ARSCNView
у SceneKit уже есть пространственное координатное пространство 3D, и ARKit делает все, чтобы сделать это пространство сопоставимым с реальным пространством, которое отображает ARKit. Итак, с учетом преобразования float4x4
, которое описывает позицию (и ориентацию и т.д.) В мировом пространстве, вы можете:
- Создайте
ARAnchor
, добавьте его в сеанс и ответьте на обратный вызовARSCNViewDelegate
, чтобы предоставить контент SceneKit для каждого якоря, который ARKit будет добавлять и позиционировать в сцене для вас. - Создайте
SCNNode
, установите егоsimdTransform
и добавьте его как дочерний элемент сценыrootNode
.
Пока у вас работает ARSession
, нет никакой разницы между этими двумя подходами - они эквивалентны, чтобы сказать то же самое. Поэтому, если вам нравится делать вещи SceneKit, нет ничего плохого в этом. (Вы можете даже использовать SCNVector3
и SCNMatrix4
вместо SIMD-типов, если хотите, но вам придется конвертировать туда и обратно, если вы также получаете SIMD-типы из API ARKit.)
Одно время эти подходы отличаются друг от друга, когда сеанс reset. Если отслеживание в мире не выполняется, вы возобновляете прерванный сеанс и/или вы снова начинаете сеанс, "мировое пространство" может больше не соответствовать реальному миру так же, как при размещении контента в сцене.
В этом случае вы можете удалить ARKit анкеры из сеанса - см. метод run(_:options:)
и ARSession.RunOptions
, (Да, все они, потому что на данный момент вы не можете доверять никому из них, чтобы они были действительными больше.) Если вы разместили контент в сцене с помощью якорей и обратных вызовов делегатов, ARKit уничтожит все содержимое. (Вы получаете ответные вызовы делегатов, которые он удаляет.) Если вы разместили контент с помощью SceneKit API, он остается в сцене (но, скорее всего, в неправильном месте).
Итак, использование какого-то типа зависит от того, как вы хотите обрабатывать сбои и прерывания сеанса (и вне этого нет никакой реальной разницы).