При создании прототипа в Reality Composer очевидно, что мы не можем активировать одновременное обнаружение вертикальной и горизонтальной плоскости, потому что в меню, а не набор опций. Но многие разработчики не могут догадаться, как это сделать даже в RealityKit. Моя история прольет свет на эту тему.
Однако в ARKit есть простой подход - мы должны использовать Свойство экземпляра planeDetection, соответствующее протоколу OptionSet. У этого свойства есть два варианта: по вертикали и по горизонтали:
let config = ARWorldTrackingConfiguration()
config.planeDetection = [.vertical, .horizontal]
sceneView.session.run(config)
Если вы хотите узнать, к какому типу выравнивания принадлежит ваш ARPlaneAnchor, вы можете проверить его с помощью простого if-else-if.
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { guard let planeAnchor = anchor as? ARPlaneAnchor else { return } if planeAnchor.alignment == .horizontal { print("Horizontal") } else if planeAnchor.alignment == .vertical { print("Vertical") } }
RealityKit
RealityKit имеет класс AnchorEntity с удобной функцией init, нацеленной на самолеты - init (plane: classification: minimumBounds :). Для случая обнаружения плоскости доступны три варианта выравнивания: вертикальное, горизонтальное или любое. .
let planeAnchor = AnchorEntity(.plane([.vertical, .horizontal],
classification: [.wall, .floor, .ceiling],
minimumBounds: [1.0, 1.0]))
Учтите: этот инициализатор не работает с приложением Simulator, поэтому убедитесь, что в активной схеме Xcode выбрано физическое устройство.
Давайте программно создадим примитив блока в файле ViewController.swift и закрепим его с нашим объектом planeAnchor:
import UIKit import RealityKit class ViewController: UIViewController { @IBOutlet weak var arView: ARView! override func viewDidLoad() { super.viewDidLoad() let boxMesh: MeshResource = .generateBox(size: 0.25) let modelEntity = ModelEntity(mesh: boxMesh) let planeAnchor = AnchorEntity(.plane([.any], classification: [.any], minimumBounds: [0.5, 0.5])) planeAnchor.addChild(modelEntity) arView.scene.anchors.append(planeAnchor) } }
Схематическое изображение сцены и коллекции привязанных к ней якорей, моделей, источников света, отслеживаемых тел, звуков окружающей среды и камер выглядит так просто:
Тем не менее, в ARKit коллекция якорей может быть доступна через объект ARSession, а не через объект Scene.
Reality Composer + RealityKit
Предположим, что мы создали простую сцену, содержащую модель часов в Reality Composer. Для этого проекта мы выбрали конфигурацию World Tracking с обнаружением вертикальной плоскости.
Поскольку у нас есть только выравнивание по вертикали, мы также можем добавить выравнивание по горизонтали. Сначала нам нужно прочитать эту сцену в Xcode. Для этого мы должны использовать оператор Swift try!, потому что мы загружаем сцену с помощью функции бросания.
let sceneAnchor = try! Experience.loadInteriorItems()
Теперь все, что нам нужно сделать, это перейти к компоненту привязки в иерархии сцены, чтобы назначить как вертикальное, так и Параметры горизонтального выравнивания.
Давайте посмотрим на иерархию сцены, чтобы узнать, где расположен объект привязка с соответствующим ему компонентом привязки. Но перед этим мы должны дать описательные имена нашей сцене и нашему якору. Это довольно просто:
sceneAnchor.name = "myScene" sceneAnchor.children[0].name = "myAnchor" sceneAnchor.children[0].children[0].name = "myEntity"
Затем просто распечатайте свойство.
print(sceneAnchor)
В соответствии с иерархией путь к компоненту привязки теперь очевиден:
sceneAnchor.children[0].anchor?.anchoring
Вставьте это в наш код:
class ViewController: UIViewController { @IBOutlet weak var arView: ARView! override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) let sceneAnchor = try! Experience.loadInteriorItems() sceneAnchor.children[0].anchor?.anchoring = AnchoringComponent(.plane([.horizontal, .vertical], classification: .any, minimumBounds: [0.2, 0.2])) arView.scene.anchors.append(sceneAnchor) } }
В любом случае, для многих из нас лучший подход - извлечь объект модели из иерархии сцены и повторно прикрепить его с помощью новой привязки любого желаемого типа. Для этого у нас есть два варианта. Первый из них следующий:
let sceneAnchor = try! Experience.loadInteriorItems() let clockEntity = sceneAnchor.children[0].children[0].children[0]
И если у модели Reality Composer есть имя (и, да, у нее есть имя, помните?), Тогда также была переменная с аналогичным именем, автоматически сгенерированная Reality Composer. Так что второй вариант намного удобнее, не правда ли?
let clockEntity = sceneAnchor.clock!
Полная версия нашего кода может выглядеть так:
class ViewController: UIViewController { @IBOutlet weak var arView: ARView! override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) let sceneAnchor = try! Experience.loadInteriorItems() let clockEntity = sceneAnchor.clock! let anchor = AnchorEntity(plane:[.horizontal, .vertical], classification: .any, minimumBounds: [0.2, 0.2]) anchor.addChild(clockEntity) arView.scene.anchors.append(anchor) } }
Вуаля!
Пожертвовать автору
addr1q9w70n62nu8p7f9ukfn66gzumm9d9uxwppkx7gk7vd7gy0ehfavj97gkncwm8t8l8l8x9e4adzmw2djh4y5gd9rmtewqr99zr3
На этом пока все.
Если эта публикация вам полезна, нажмите кнопку Хлопать и удерживайте ее. На Medium вы можете аплодировать до 50 за каждое сообщение.
Если у вас есть вопросы, вы можете связаться со мной через StackOverflow.
До встречи!