본문 바로가기
IOS - Swift

[WWDC 2022]Create parametric 3D room scans with RoomPlan

by 게게겍 2023. 6. 11.

원본

  • 작년에 소개된 Object Capture
    • 현실 세계의 사진을 찍으면, RealityKit의 Photogrammetry API를 사용해서 앱에서 사용할 수 있는 3D모델을 만들어주는 기능
  • 그 전에는 Scene Reconstruction API를 릴리즈 했었다.
    • 공간의 대략적인 구조에 대한 정보를 제공해서, AR에 사용할 수 있도록 한다.
  • 올해는 RoomPlan이라는 프레임워크를 새로 제공한다.
    • LiDAR를 가진 아이폰이나 아이패드로 방을 스캔하면 방 3D 모델을 만들어준다.
    • ARKit에서 제공하는 머신러닝 알고리즘을 이용해서 벽, 창문, 문, 화로, 소파, 탁자, 옷장 등의 물건을 식별한다.
  • RoomCaptureView API를 쓰면 RealityKit의 스캐닝 프로세스를 실시간으로 사용해서 앱에 스캔 과정을 쉽게 적용할 수 있다.
    • 스캔이 완료되면 3D모델이 나오고, 이를 보여주게 된다.
RealityKit + ARKit을 활용해서 특정 UseCase에 특화된 프레임워크를 만들어낸 것.
  • 활용 예시
    • 인테리어 디자인
      • 벽 색깔 미리 바꿔보기
      • 다시 칠하는 데 들어가는 페인트 양 계산하기
    • 설계 앱
      • 설계 미리 보기
      • 설계 실시간으로 변경하기
    • 부동산 앱
    • 이커머스 앱
      • 물리적인 공간에서 상품을 시각화시키기
  • Scanning Experience API
    • 핵심 API: RoomCaptureView
      • UIView 서브클래스
      • 주요 기능
        • world space scanning feedback
        • Realtime model generation
        • Coaching and user guidance
      • 세션이 활성화 된 동안, 실시간으로 방의 오브젝트들을 찾아 윤곽선을 그린다.
      • 뷰 아래에서는 3D 모델이 실시간으로 만들어져서 보여진다.
    • 코드
      • 시작하기
// RoomCaptureView API - Scan & Process

import UIKit
import RoomPlan

class RoomCaptureViewController: UIViewController {

    var roomCaptureView: RoomCaptureView
    var captureSessionConfig: RoomCaptureSession.Configuration

   private func startSession() {
        roomCaptureView?.captureSession.run(configuration: captureSessionConfig)
     }
    
    private func stopSession() {
        roomCaptureView?.captureSession.stop()
	}
}

RoomCaptureViewDelegate

import UIKit
import RoomPlan

class RoomCaptureViewController: UIViewController {
  …
  func captureView(shouldPresent roomDataForProcessing: CapturedRoomData, error: Error?) -> Bool {
    // Optionally opt out of post processed scan results.
    return false
  }

  func captureView(didPresent processedResult: CapturedRoom, error: Error?) {
    // Handle final, post processed results and optional error.
    // Export processedResults
    …
    try processedResult.export(to: destinationURL)
    …
  }
}
  • data API: 스캔 중인 데이터에 접근할 수 있게 해준다.
    • 기본 워크플로우
      • scan - RoomCaptureSession
        • 세션 시작
        • 캡쳐 과정을 실시간으로 보여주기 - ARView 활용
import UIKit
import RealityKit
import RoomPlan
import ARKit

class ViewController: UIViewController {
    @IBOutlet weak var arView: ARView!
    var previewVisualizer: Visualizer!
    lazy var captureSession: RoomCaptureSession = {
        let captureSession = RoomCaptureSession()
        arView.session = captureSession.arSession
        return captureSession
    }()
    override func viewDidLoad() {
        super.viewDidLoad()
        captureSession.delegate = self
        // set up previewVisualizer
    }
}

// Getting live results and user instructions

extension ViewController: RoomCaptureSessionDelegate {

		// 방 구조가 업데이트 될 때마다 불린다.
    func captureSession(_ session: RoomCaptureSession,
                        didUpdate room: CapturedRoom) {
        previewVisualizer.update(model: room)
    }
    
		// real-time feedback을 포함하는 instruction이 화면에 나타날 때 불린다.
		// Move closer to wall
		// Move away from wall
		// Slow down
		// Turn on light
		// Low texture
    func captureSession(_ session: RoomCaptureSession,
                   didProvide instruction: Instruction) {
        previewVisualizer.provide(instruction)
    }
}
  • process - RoomBuilder
    • 스캔한 데이터를 처리하기
    • 최종 모델을 만들어낸다.
import UIKit
import RealityKit
import RoomPlan
import ARKit

class ViewController: UIViewController {
    
    @IBOutlet weak var arView: ARView!
    var previewVisualizer: Visualizer!

    // set up RoomBuilder
    var roomBuilder = RoomBuilder(options: [.beautifyObjects])
}

extension ViewController: RoomCaptureSessionDelegate
{
    func captureSession(_ session: RoomCaptureSession, 
                        didEndWith data: CapturedRoomData, error: Error?)
    {
        if let error = error {
            print("Error: \(error)")
        }
        Task {
            let finalRoom = try! await roomBuilder.capturedRoom(from: data)
            previewVisualizer.update(model: finalRoom)
        }
    }
}

 

  • export - CaptureRoom
    • 최종 모델을 USD/USDZ로 만들어냄
    • USD/USDZ 파일을 내보냄
    • 구조
      • Surface
        • curve(radius, starting/end angle), edge(left, right, top, bottom), category(wall, opening, window, door)등의 정보를 가짐
      • Object
        • 가구 카테고리(table, bed, sofa) 정보를 가짐
      • 공통 attribute
        • Dimension
        • Confidence
        • Transform
        • Identifier
// CapturedRoom and export

public struct CapturedRoom: Codable, Sendable
{
    public let walls: [Surface]
    public let doors: [Surface]
    public let windows: [Surface]
    public let openings: [Surface]
    public let objects: [Object]

    public func export(to url: URL) throws

		public struct Surface: Codable, Sendable {
			public let category: Category
			public let confidence: Confidence
			public let dimensions: simd_float3
			public let transform: simd_float4x4
			public let identifier: UUID
			public let curve: Curve?
		
			public enum Category: Codable, Sendable {
				case wall
				case opening
				case window
				case door(isOpen: Bool)
			}
		}

		public struct Object: Codable, Sendable {
			public let category: Category
			public let confidence: Confidence
			public let dimensions: simd_float3
			public let transform: simd_float4x4
			public let identifier: UUID
			
			public let Category: Codable, Sendable {
				case bathtub
				case bed
				case chair
				case dishwasher
				case fireplace
				case oven
				case refrigerator
				case sink
				case sofa
				case stairs
				case storage
				case stove
				case table
				case television
				case toilet
				case washerDryer
			}
		}
}
  • Best Practices
    • 권장 조건
      • 단일 방 구조에서 가장 잘 동작
      • 30 ft by 30 ft(9m * 9m)가 최대
      • 방 밝기가 최소 50lux는 되어야 함
        • 밤의 거실 밝기 정도
      • LiDAR가 있는 하드웨어는 모두 가능
    • 스캔이 어려운 조건 → LiDAR 센서의 제한
      • 전신 거울이나 유리가 있는 경우 - 센서 오작동 가능성 높음
      • 높은 천장 - 센서 스캔 범위 초과 가능성
      • 너무 어두운 벽면
    • 스캔시 고려사항
      • 방을 미리 준비해두면 좋다.
        • 낮에는 커튼을 열어두기
        • 문은 닫기
      • 이러한 고려 사항들에 대한 안내를 위해 instruction을 제공하는 것이다.
    • 온도 고려사항
      • 반복적으로 스캔하거나 5분 이상 장시간 스캔하는 것은 배터리와 기기 온도에 좋지 않다.