Всем привет, с вами я, Наиль Габутдинов, iOS разработчик.
На WWDC 2022 Apple представила новый инструмент RoomPlan, реализованный на основе ARKit 6, который использует LiDAR датчик на новейших iPhone и iPad для быстрого создания 3D планов комнат. По словам Apple, API может быть полезен для приложений в сфере недвижимости, архитектуры и дизайна интерьеров, поскольку он, с одной стороны, точен и гибок в настройке и экспортировании результатов а, с другой стороны, достаточно прост в использовании. Так ли это, давайте разбираться.

У RoomPlan есть два основных режима использования:
Первый — это полностью готовое решение для сканирования помещения (жилой комнаты) со стандартным интерфейсом, которое легко интегрируется в приложение.
Второй — это более глубокий и гибкий подход, который позволяет вашему приложению самостоятельно настраивать параметры сеанса сканирования, использовать получаемые параметрические данные в режиме реального времени, реализовывать постобработку и получать доступ к детализированному результату.
Давайте рассмотрим оба этих режима подробнее.
Простой API для сканирования
RoomCaptureView — это подкласс UIView, который мы можем просто добавить в свое приложение. Он содержит в себе весь функционал сканирования, а также показа результата и подсказок для пользователя в реальном времени.
Давайте рассмотрим, как начать использовать RoomCaptureView в приложении, написав всего несколько строк кода:
import UIKit
import RoomPlan
class ViewController: UIViewController {
//1
private var roomCaptureView: RoomCaptureView!
//2
private var captureSessionConfig = RoomCaptureSession.Configuration()
override func viewDidLoad() {
super.viewDidLoad()
roomCaptureView = RoomCaptureView()
self.view.addSubview(roomCaptureView)
}
//3
private func startSession() {
roomCaptureView.captureSession.run(configuration: captureSessionConfig)
}
//4
private func stopSession() {
roomCaptureView.captureSession.stop()
}
}Создаем ссылку на RoomCaptureView в наш ViewController. Инициализируем и добавляем его как обычный UIView.
Добавляем ссылку на объект конфигурации RoomCaptureSession, инициализируем данный объект.
Реализуем запуск сеанса сканирования, передавая нашу конфигурацию функции run.
Также нужно реализовать остановку сеан��а сканирования через функцию stop.
При необходимости можно добавить методы протокола RoomCaptureViewDelegate и, например, отказаться от показа результатов постобработки.
extension ViewController: RoomCaptureViewDelegate {
func captureView(shouldPresent roomDataForProcessing: CapturedRoomData, error: Error?) -> Bool {
return false
}
}Также, если нужно, мы можем экспортировать результаты сканирования в формат USDZ, вызвав функцию export, доступную в структуре CapturedRoom, которую получаем в методе captureView(didPresent: error: ).
func captureView(didPresent processedResult: CapturedRoom, error: Error?) {
try processedResult.export(to: URL)
}Data API для гибкого использования
В данном разделе разберем базовые структуры данных, к которым дает доступ RoomPlan в процессе сканирования, во время обработки и после получения результата. Эти данные помогают нам самим настраивать визуализацию процесса сканирования и использовать полученный результат для дальнейшей работы.

Общий рабочий процесс RoomPlan состоит из трех частей: сканирование, обработка и экспорт. Рассмотрим их подробнее.
Сканирование
Процесс сканирования комнаты в свою очередь можно разделить на:
настройку и запуск сеанса,
отображение прогресса по мере прохождения по комнате.

В RoomPlan API есть сущность RoomCaptureSession, она нужна для настройки сеанса и для получения текущей информации о процессе сканирования. Давайте рассмотрим её в коде:
class ViewController: UIViewController {
@IBOutlet weak var arView: ARView!
lazy var captureSession: RoomCaptureSession = {
let captureSession = RoomCaptureSession()
arView.session = captureSession.arSession
return captureSession
}
private var captureSessionConfig = RoomCaptureSession.Configuration()
private func startSession() {
captureSession.run(configuration: captureSessionConfig)
}
private func stopSession() {
captureSession.stop()
}
}Мы просто добавляем новое свойство RoomCaptureSession во ViewController, предварительно сделав импорт ARKit и RoоmPlan. В нужный момент можем запустить сеанс, вызвав функцию run(configuration: ) и передав конфигурацию, и остановить функцией stop().
RoomCaptureSession предоставляет доступ к основному сеансу ARSession, чтобы приложение могло отображать отсканированные плоскости и ограничивающие рамки объектов в AR представлении.

Кроме того, RoomCaptureSession имеет свойство delegate. Назначение ViewController делегатом позволит получать обновления от RoomCaptureSession в режиме реального времени. Эти обновления включают в себя 3D-модели и рекомендации по текущему сканированию.
Чтобы получать эти обновления, ViewController должен соответствовать протоколу RoomCaptureSessionDelegate, который включает в себя два метода:
extension ViewController: RoomCaptureSessionDelegate {
func captureSession(_ session: RoomCaptureSession, didUpdate room: CapturedRoom) {
//Обработка данных и поверхностях и объектов ко��наты в real-time.
}
func captureSession(_ session: RoomCaptureSession, didProvide instruction: RoomCaptureSession.Instruction) {
//Обработка и показ поступающих инструкций (рекомендаций).
}
}Первый — это метод captureSession(_ session: didUpdate room:) для получения структуры данных о сканируемой комнате CapturedRoom в реальном времени. Приложение может использовать объект CapturedRoom для визуализации в AR-режиме прогресса текущего сканирования, отображая уже отсканированные поверхности и объекты. Подробнее CapturedRoom рассмотрим ниже. Данный метод вызывается при обнаружении обновлений (изменение геометрии зафиксированных ранее поверхностей, появление новых поверхностей и объектов) в комнате.
Второй метод — это captureSession(_ session: didProvide instruction:). Он позволяет получать полезные инструкции (рекомендации) от RoomPlan API в контексте текущего процесса сканирования комнаты.

Эти инструкции можно использовать для отображения в интерфейсе в режиме реального времени, чтобы пользователь получал обратную связь, как отсканировать комнату оптимально. Инструкции могут касаться следующих параметров:
расстояние до объектов,
скорость сканирования,
уровень освещения в помещении,
фокусировка на определенных областях комнаты, которые имеют больше текстур.
Обработка
В этой части рассмотрим, как отсканированные данные будут обработаны и итоговая 3D модель будет получена для показа. Для этого используется класс RoomBuilder.

class ViewController: UIViewController {
@IBOutlet weak var arView: ARView!
var roomBuilder = RoomBuilder(options: [.beautifyObjects])
}Первым делом нужно создать экземпляр RoomBuilder в нашем ViewController. Далее, чтобы получить данные с сенсоров после процесса сканирования, приложение должно реализовать метод captureSession(_ session: didEndWith data: error:), это метод протокола RoomCaptureSessionDelegate, который мы рассматривали выше.
extension ViewController: RoomCaptureSessionDelegate {
func captureSession(_ session: RoomCaptureSession, didEndWith data: CapturedRoomData, error: Error?) {
if let error = error {
// Обработка ошибки
print(error)
}
Task {
if let finalRoom = try? await roomBuilder.capturedRoom(from: data) {
// Показ итоговой модели
preview.update(model: finalRoom)
}
}
}
}Когда RoomCaptureSession останавливается, этот метод будет вызываться для возврата объекта CaptureRoomData и возможной ошибки, из-за которой произошла остановка. Наконец, для обработки полученных данных мы вызываем асинхронный метод captureRoom(from:) из roomBuilder. Метод реализует обработку отсканированных данных и построение итоговой 3D-модели, это занимает какое-то время (несколько секунд для комнаты), поэтому он выполняется асинхронно.
Экспорт

Выше я уже упоминал структуру CapturedRoom, которая представляет собой результат сканирования и обработки. Давайте углубимся в детали: какие данные она содержит, каким образом ее можно экспортировать для последующей работы в других программах.

На верхнем уровне CapturedRoom состоит из обнаруженных поверхностей и объектов.
Поверхность содержит следующие атрибуты:
свойства кривых, такие как радиус, начальный и конечный углы;
четыре разных края поверхности;
архитектурная категория поверхности (стена, проём, окно, дверь).
Объект имеет атрибут category, это может быть, например, стол, кровать, диван и т. д.
Поверхность и объект имеют некоторые общие атрибуты, такие как размеры, уровень достоверности (уверенности) при определении, матрица трехмерного преобразования, а также уникальный идентификатор.
Давайте посмотрим, как они представлены в коде.
public struct CapturedRoom : Codable, Sendable {
public var walls: [CapturedRoom.Surface] { get }
public var doors: [CapturedRoom.Surface] { get }
public var windows: [CapturedRoom.Surface] { get }
public var openings: [CapturedRoom.Surface] { get }
public var objects: [CapturedRoom.Object] { get }
public func encode(to encoder: Encoder) throws
...
}CapturedRoom содержит пять свойств: стены, проемы, двери, окна и объекты в комнате. Первые четыре атрибута представляют собой массивы поверхностей Surface, которые разделены по категориям.
Последнее свойство objects — это массив 3D-объектов в комнате, каждый из которых представляет собой прямоугольный параллелепипед с определенной категорией (диван, стол, стул, кровать и т. д).
Наконец, функция экспорта export(to: ) позволяет экспортировать полученный результат в файлы формата .USD или .USDZ для дальнейшей работы с ними в различных 3D инструментах.
Рекомендации по сканированию
Apple приводит рекомендации по сканированию, которые помогут добиться лучших результатов с помощью RoomPlan:
Объектом для сканирования могут быть отдельные жилые комнаты;
Максимальный размер комнаты – 30x30 футов или около 9x9 метров;
Уровень освещенности – 50 lux или выше.
RoomPlan API поддерживается на всех моделях iPhone и iPad Pro с поддержкой LiDAR.
Вывод
Существующие приложения, способные создавать 3D планы комнат с помощью камеры телефона, не совсем новы, но и не совсем точны. С появлением сканеров LiDAR с iPad Pro 2020 года и iPhone 12 Pro, стало возможным более точно определять размеры объектов и расстояния до них. Как видим, в этом году Apple сама сделала для нас готовый и мощный инструмент для сканирования комнат, позволяющий определять все значимые поверхности и объекты в комнате, точно определять их размеры и расположение, отрисовывать в режиме реального времени прогресс по процессу, давать пользователям полезные подсказки, как лучше сканировать, получать доступ к детальной структуре результата и экспортировать его в удобном формате.
Я считаю, это действительно прорывная технология, применимая в профессиональных приложениях, и в скором времени она может существенно изменить процесс работы архитекторов, дизайнеров интерьеров и специалистов по жилой недвижимости.
