WWDC Quick Look 💓 By SwiftGGTeam
Explore enhancements to RoomPlan

Explore enhancements to RoomPlan

元の動画を見る

ハイライト

RoomPlan は、複数部屋のスキャンの結合、カスタム ARSession 統合、VoiceOver アクセシビリティ、iOS 17 のスキャン結果のブロック オブジェクトの 3D モデルへの置き換えをサポートし、プロパティ マッピング、インテリア デザイン、スペース プランニング アプリケーションを単一部屋ツールから完全なスペース ソリューションにアップグレードします。

主要内容

iOS 16 以降、RoomPlan では iPhone と iPad に部屋をスキャンして 3D モデルを生成する機能が提供されます。しかし、最初のバージョンには明らかな制限があります。スキャンできる部屋は 1 つだけ、スキャン時に他の AR 機能と組み合わせることはできず、スキャン結果の家具は色付きの四角形だけです。

iOS 17 の 4 つのアップデートは、これらの問題点に対処します。

カスタム ARSession

(01:36) 以前は、RoomPlan が単独で ARSession を管理しており、開発者はプラグインできませんでした。初期化中にカスタム ARSession を渡すことができるようになりました。

// RoomCaptureSession 现在接受可选的 ARSession
public class RoomCaptureSession {
    public init(arSession: ARSession? = nil) {
        // ...
    }

    public func stop(pauseARSession: Bool = true) {
        // ...
    }
}

これにより、いくつかの新しいシナリオが可能になります。

  • AR インタラクティブ機能強化: RoomPlan のスキャン結果と ARKit のシーン ジオメトリおよび平面検出を組み合わせて、仮想コンテンツを現実空間により正確に適合させます。
  • 不動産表示のアップグレード: ARKit を使用して、部屋をスキャンしながら高品質の写真とビデオを収集し、3D モデルと実際の写真を含む物件ページを生成します。
  • 既存の AR に干渉しません: 既存の AR エクスペリエンスに RoomPlan を追加しても、既存の ARAnchor は破壊されません。

03:20stop(pauseARSession:)pauseARSessionこのパラメーターは、スキャン終了後に ARSession を実行し続けるかどうかを制御します。に設定false、ARSession はアクティブなままで、次の機能または次のスキャンの準備をします。

複数の部屋のスキャン

(03:53) 以前は、リビング ルーム、次に寝室をスキャンした後、2 つの部屋は独立しており、異なる座標系を持っていました。手動で結合すると、壁や家具が重複するという問題も発生します。

iOS 17 では、複数の部屋が同じ座標系を共有するための 2 つのソリューションが提供されています。

オプション 1: 継続的な ARSession

(05:02) 最初の部屋をスキャンした後、ARSession を一時停止せずに、次の部屋のスキャンを直接開始します。

// 开始第一次扫描
roomCaptureSession.run(configuration: captureSessionConfig)

// 结束第一次扫描,但保持 ARSession 运行
roomCaptureSession.stop(pauseARSession: false)

// 开始第二次扫描
roomCaptureSession.run(configuration: captureSessionConfig)

// 结束第二次扫描(默认暂停 ARSession)
roomCaptureSession.stop()

キーポイント:

  • pauseARSession: falseスキャン間で ARSession を実行し続ける
  • 同じroomCaptureSessionインスタンスは同じ ARSession を再利用します
  • すべてのスキャン結果は自動的に同じ世界座標系を共有します

オプション 2: ARSession の再配置

(06:38) 今日はリビングルームをスキャンし、明日は寝室をスキャンするなど、期間をまたいでのスキャンに適しています。

// 加载之前保存的 ARWorldMap
let arWorldMap = try NSKeyedUnarchiver.unarchivedObject(
    ofClass: ARWorldMap.self,
    from: data
)

// 配置 ARKit 重定位
let arWorldTrackingConfig = ARWorldTrackingConfiguration()
arWorldTrackingConfig.initialWorldMap = arWorldMap

roomCaptureSession.init()
roomCaptureSession.arSession.run(arWorldTrackingConfig, options: [])

// 等待重定位完成...

// 开始第二次扫描
roomCaptureSession.run(configuration: captureSessionConfig)

// 结束第二次扫描
roomCaptureSession.stop()

キーポイント:

  • 最初のスキャン後に保存しますARWorldMap- 2回目のスキャンの前にロードARWorldMapトリガーの再配置
  • 再配置が完了すると、現在の座標系は以前の座標系と一致します。
  • さまざまな期間や時間でのスキャンに適しています

ルームの結合: StructureBuilder

(09:40) 複数の部屋をスキャンした後、次を使用しますStructureBuilderマージ:

// 创建 StructureBuilder 实例
let structureBuilder = StructureBuilder(option: [.beautifyObjects])

// 加载多个 CapturedRoom
var capturedRoomArray: [CapturedRoom] = []

// 合并为 CapturedStructure
let capturedStructure = try await structureBuilder.capturedStructure(
    from: capturedRoomArray
)

// 导出为 USDZ
try capturedStructure.export(to: destinationURL)

キーポイント:

  • StructureBuilder重複した壁と重複したオブジェクトを自動的に処理する -.beautifyObjectsオブジェクト表現を美しくするオプション
  • 出力CapturedStructure結合後の完全な空間情報が含まれます

10:11CapturedStructure構造は次のとおりです。

public struct CapturedStructure: Codable, Sendable {
    public var rooms: [CapturedRoom]
    public var walls: [Surface]
    public var doors: [Surface]
    public var windows: [Surface]
    public var openings: [Surface]
    public var objects: [Object]
    public var floors: [Surface]
    public var sections: [Section]

    public func export(
        to url: URL,
        metadataURL: URL? = nil,
        modelProvider: ModelProvider? = nil,
        exportOptions: USDExportOptions = .mesh
    ) throws
}

キーポイント:

  • roomsアレイは各部屋の元の情報を保持します -wallsdoorswindowsマージと重複排除の結果を待ちます。 -sections部屋のさまざまな機能エリア(リビングルーム、ベッドルームなど)について説明します。
  • オプションでメタデータと 3D モデルを含む USDZ へのエクスポートをサポート

スキャンエクスペリエンスの最適化

(11:11) 複数の部屋のスキャンのベスト プラクティス:

  • 平屋建ての家、寝室が 1 ~ 4 つある一般的なフロアプランに適しています。
  • 総スキャン領域は 2000 平方フィート (約 186 平方メートル) 以下であることをお勧めします。
  • 照明条件は 50 ルクス以上であることが推奨されます。
  • システムの位置合わせを支援するために、スキャンセグメント間の画像の重なりを維持します

VoiceOver のサポート

(12:00) RoomCaptureView は、視覚障害のあるユーザーもスキャン機能を使用できるように、VoiceOver 音声フィードバックを追加します。

  • “Move device to start”
  • “Point camera at bottom edge of wall”
  • “A fireplace. A wall.”
  • “A window.”

システムは検出された物体とスキャンの進行状況を口頭で説明するため、視覚障害のあるユーザーは視覚的なフィードバックに頼る必要がなくなりました。

より豊かな部屋の表現

(12:32) RoomPlan は、より多くの部屋タイプとオブジェクト構成をサポートするようになりました。

  • 傾斜壁と曲面壁: 以前は直線壁のみを処理できましたが、多角形で記述された特殊な形状の壁もサポートされるようになりました。
  • 埋め込み型キッチン機器: 食器洗い機、オーブン、シンクなどの埋め込み型機器を検出し、正しくレンダリングできます。
  • ソファ構成: シングルソファ、L字型ソファ、正方形ソファなどのさまざまな形状を認識できます。
  • セクションエリア: 部屋は、リビングルーム、ベッドルーム、キッチン、ダイニングルームなどの機能エリアに分割できます。
  • 父と子の関係: 窓は特定の壁に属し、椅子は特定のテーブルに属し、食器洗い機は特定のキャビネットに属します。

ブロックを 3D モデルに置き換える

(17:26) 以前のスキャンでは、家具は色付きの四角形として表示されていました。これで、実際の 3D モデルに置き換えることができます。

ステップ 1: モデル ディレクトリを作成する

// 遍历所有支持的物体类别
for category in CapturedRoom.Object.Category.allCases {
    let url = generateFolderURL(category: category, attributes: [])
    FileManager.default.createDirectory(at: url, withIntermediateDirectories: true)

    // 为每个属性组合创建子文件夹
    for attributes in category.supportedCombinations {
        let url = generateFolderURL(category: category, attributes: attributes)
        FileManager.default.createDirectory(at: url, withIntermediateDirectories: true)
    }
}

ステップ 2: ディレクトリ インデックスを作成する

struct RoomPlanCatalog: Codable {
    let categoryAttributes: [RoomPlanCatalogCategoryAttribute]
}

struct RoomPlanCatalogCategoryAttribute: Codable {
    let category: CapturedRoom.Object.Category
    let attributes: [any CapturedRoomAttribute]
    let folderRelativePath: String
    private(set) var modelFilename: String? = nil
}

ステップ 3: カタログ バンドルにパッケージ化する

let catalog = RoomPlanCatalog(categoryAttributes: categoryAttributes)
let plistEncoder = PropertyListEncoder()
let data = try plistEncoder.encode(catalog)
let catalogURL = inputURL.appending(path: "catalog.plist")
try data.write(to: catalogURL)

let fileWrapper = try FileWrapper(url: inputURL)
try fileWrapper.write(
    to: outputURL,
    options: [.atomic, .withNameUpdating],
    originalContentsURL: nil
)

ステップ 4: カタログから ModelProvider を作成します

for categoryAttribute in catalog.categoryAttributes {
    guard let modelFilename = categoryAttribute.modelFilename else {
        continue
    }
    let folderRelativePath = categoryAttribute.folderRelativePath
    let modelURL = url.appending(path: folderRelativePath).appending(path: modelFilename)

    if categoryAttribute.attributes.isEmpty {
        try modelProvider.setModelFileURL(modelURL, for: categoryAttribute.category)
    } else {
        try modelProvider.setModelFileURL(modelURL, for: categoryAttribute.attributes)
    }
}

ステップ 5: USDZ をモデルとともにエクスポート

try capturedRoom.export(
    to: outputURL,
    modelProvider: modelProvider,
    exportOptions: .model
)

キーポイント:

  • ModelProviderオブジェクトのカテゴリとプロパティを 3D モデルの URL にマッピングする
  • 属性のないオブジェクトはカテゴリによって照合され、属性のあるオブジェクトは属性の組み合わせによって照合されます。
  • エクスポート時に指定.modelブロックを実際のモデルに置き換えるオプション
  • サンプル コードには、開始点として事前設定されたモデル ディレクトリが含まれています

メタデータのマッピング

(16:08) USDZ をエクスポートするときに、メタデータ マッピング ファイルを添付して、USDZ ノードを CapturedRoom 要素に関連付けることができます。

try capturedRoom.export(
    to: outputURL,
    metadataURL: metadataURL
)

生成されたマッピング ファイルは文字列から UUID までの辞書であり、スキャン結果をレンダリングするときに壁の寸法やオブジェクトのプロパティなどの追加情報をクエリできるようになります。

詳細

オブジェクト属性の詳細な説明

RoomPlan は属性を使用してオブジェクトをより正確に記述するようになりました。椅子を例に挙げます。

  • カテゴリー:椅子
  • 属性: スツール (スツール)、ダイニングチェア (ダイニングチェア)、オフィスチェア (オフィスチェア) にすることができます。

属性は多態性列挙配列を通じて公開されますが、その処理は十分直感的ではありません。組み合わせるのがオススメですModelProvider属性を特定の 3D モデルにマップします。

壁と床の多角形表現

不均一な壁が使用されるようになりましたpolygonCorners多角形として記述されます。床はスキャン中は長方形として表示されますが、スキャンが完了すると多角形に変換されます。 RoomCaptureView の最終結果では、湾曲した壁と湾曲した窓もレンダリングされます。

エクスポート オプションの比較

オプション出力使い方
.meshメッシュUSDZユニバーサル 3D プレビュー
.modelUSDZ とモデル本物の家具モデルが必要なシナリオ
metadataURLマッピングファイル追加情報を問い合わせる

重要ポイント

1.不動産表示申請書の作成

  • やるべきこと: 家全体をスキャンして 3D モデルを生成し、高品質の写真と組み合わせて没入型のリスト表示を作成します。
  • 実行する価値がある理由: マルチルームの結合 + カスタム ARSession により、スキャンと写真の撮影を同時に行うことができ、ModelProvider により家具を実際のモデルとして表示できるようになります。
  • 開始方法: 継続的な ARSession で各部屋をスキャンし、StructureBuilder と結合し、メタデータを含む USDZ をエクスポートし、Quick Look を使用して Web ページに表示します。

2.インテリア デザイン計画ツールを作成する

  • やるべきこと: クライアントの部屋をスキャンし、3D モデルで家具の配置をプレビューします。
  • 実行する価値がある理由: RoomPlan は壁、ドア、窓の位置を自動的に検出し、Section は機能エリアを区別し、ModelProvider はブロックを実際の家具モデルに置き換えます。
  • 開始方法: 部屋をスキャンして構造を取得し、ModelProvider を使用して家具カタログをロードし、AR で配置効果をリアルタイムでプレビューします。

3.バリアフリー空間ナビゲーションアプリを作る

  • 内容: 視覚障害のあるユーザーが見慣れない空間のレイアウトを理解できるように支援します。
  • 実行する価値がある理由: VoiceOver はスキャン プロセス自体のバリアフリー化をサポートしており、スキャン結果で部屋の構造やオブジェクトの位置を音声で説明できます。
  • 開始方法: RoomCaptureView を統合し、スキャン後に検出された壁、ドア、窓、家具とそれらの相対位置を音声を使用してブロードキャストします。

4.家具EC向けARプレビュー機能を作る

  • やるべきこと: ユーザーは自分の部屋をスキャンし、実空間の e コマース プラットフォームで家具をプレビューします。
  • 実行する価値がある理由: RoomPlan は正確な部屋の形状を提供し、カスタム ARSession は平面検出を実行し、同時に仮想家具を配置できます。
  • 開始方法: RoomPlan を使用して部屋の構造を取得し、ARKit 平面検出を使用して床/壁に家具モデルを配置し、ModelProvider と組み合わせて実際の製品モデルを使用します。

関連セッション

コメント

GitHub Issues · utterances