-
Notifications
You must be signed in to change notification settings - Fork 1
Description
RoomPlan
새 프레임워크!
방을 스캔할 수 있으며, LiDAR를 지원하는 iPhone이나 iPad에서 사용할 수 있다.
방과 방을 정의하는 물체들의 매개 변수 3D 모델을 앱에서 사용할 수 있도록 생성해준다.
RoomPlan은...
- ARKit을 사용하여 → 벽, 창문, 개구부, 문뿐만 아니라 방을 정의하는 물체들인 벽난로, 소파, 탁자, 진열정까지 감지.
- RealityKit 사용하여 → 스캐닝과 동시에 렌더링.
- 스캔이 완료되면 사용하기에 적합한 후처리 결과를 제공.
→ 기계 학습과 컴퓨터 비전 알고리즘을 복잡하게 구현하지 않고도 본인의 방을 스캔하고 렌더링할 수 있게 됐다!
적용할만한 예시
-
Interior design
인테리어 디자인 앱으로 벽의 색상 변화를 미리 보고 방을 다시 칠하는 데 필요한 페인트 양을 정확히 계산할 수 있다.
-
Architecture
건축 앱을 통해 자기 방의 구조를 실시간으로 미리 보고 편집할 수 있다.
-
Real estate
부동산 앱을 통해 중개인은 이제 매물의 평면도와 3D 모델을 완벽하게 포착할 수 있다.
-
E-commerce
전자 상거래 앱은 실제 공간에서 제품 시각화를 통해 고객을 끌어들일 수 있다.
사용하기
RoomPlan은 두 가지 API를 제공한다.
-
Scanning experience API
RoomPlan을 앱에서 사용하는 방법.
-
Data API
스캔의 실시간 매개 변수 데이터를 앱이 사용할 수 있도록 처리하는 방법.
1. Scanning Experience API
RoomCaptureView
Code
이제 RoomCaptureView를 앱에서 사용할 수 있도록 코드를 작성하는 방법을 알아보자
- 먼저 RoomPlan을 import한다.
import UIKit
import RoomPlan- ViewController에 RoomCaptureView 레퍼런스와 RoomCaptureSession의 Configuration 레퍼런스를 생성한다.
class RoomCaptureViewController: UIViewController {
var roomCaptureView: RoomCaptureView!
var captureSessionConfig: RoomCaptureSession.Configuration = RoomCaptureSession.Configuration()
private func setupRoomCaptureView() {
roomCaptureView = RoomCaptureView(frame: view.bounds)
}
override func viewDidLoad() {
super.viewDidLoad()
setupRoomCaptureVIew()
}
}- 스캔 세션을 시작하고 끝낼 메서드를 만든다.
class RoomCaptureViewController: UIViewController {
private func startSession() {
roomCaptureView?.captureSession.run(configuration: captureSessionConfig)
}
private func stopSession() {
roomCaptureView?.captureSession.stop()
}
}- 스캔 세션을 시작하고 끝내는 메서드를 적절한 시기에 호출한다.
class RoomCaptureViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
startSession()
}
override func viewWillDisappear(_ flag: Bool) {
super.viewWillDisappear(flag)
stopSession()
}
}이렇게 하면 스캔 과정을 앱에 적용할 수 있다.
이제 스캔 결과를 어떻게 내보내게 할지를 알아보자.
- ViewController가 RoomCaptureViewDelegate를 준수하도록 만든다.
extension RoomCaptureViewController: RoomCaptureViewDelegate {
}captureView(shouldPresent roomDataForProcessing: CapturedRoomData, error: Error?)메서드를 구현한다.
extension RoomCaptureViewController: RoomCaptureViewDelegate {
func captureView(shouldPresent roomDataForProcessing: CapturedRoomData, error: Error?) -> Bool {
return true
}
}이 함수가 true를 반환하면 스캔이 중지됐을때 스캔 결과를 보여주는 화면을 표시하게 된다.
captureView(didPresent processedResult: CapturedRoom, error: Error?)메서드를 구현한다.
extension RoomCaptureViewController: RoomCaptureViewDelegate {
func captureView(didPresent processedResult: CapturedRoom, error: Error?) {
finalResults = processedResult
}
}이 함수의 processedResult가 바로 스캔 결과를 담는다.
이를 이용하여 스캔 결과물을 어디로, 어떤 형식으로 내보낼 것인지 정할 수 있다.
func exportResults() {
let destinationURL = FileManager.default.temporaryDirectory.appending(path: "Room.usdz")
do {
try finalResults?.export(to: destinationURL, exportOptions: .parametric)
} catch {
// ...
}
}.parametric: An export option that formats the output file as a collection of independent, size-agnostic polygonal units..mesh: A export option that formats the output file as a collection of size-dependent triangles that connect to form a mesh.
2. Data API
스캔 중에 기본 데이터 구조에 접근할 수 있게 하고, 스캔 환경의 맞춤형 시각화를 처음부터 구축하는 걸 도와준다.
기본 워크플로우 3단계.Scan
- 캡처 세션을 설정하고 시작하는 단계.
- 캡처 프로세스를 표시하고 모니터링할 수 있다.
-
RoomCaptureSession은 기본 AR 세션에 대한 핸들을 제공해 앱이 증강 현실 화면에 평면과 물체 경계 상자를 그릴 수 있게 한다.
-
RoomCaptureSession은 delegate 패턴을 사용하여 뷰컨을 captureSession의 delegate로 할당할 수 있다.
이렇게 되면 뷰컨이 RoomCaptureSession에서 실시간 업데이트를 가져올 수 있게 된다. -
뷰컨이 delegate 역할을 하여 실시간 업데이트를 가져오려면 RoomCaptureSessionDelegate를 준수하고 두 가지 메서드를 구현해야 한다.
- captureSession(_ session: didUpdate room:) 메서드로 CapturedRoom 데이터 구조를 실시간으로 얻게 된다.
Visualizer는 이걸 사용해서 process에 실시간 피드백을 제공하는 3D 모델의 AR 화면을 업데이트할 수 있게 된다.
이 메서드는 스캔하는 방에 대해 업데이트가 감지될 때 호출된다.
- captureSession(_ session: didProvide instruction:) 메서드는 텍스트 코칭같은 실시간 피드백을 포함하는 instruction 구조체를 제공한다.
- Visualizer는 이 instruction을 사용해 스캔하는 동안 사용자를 안내한다.
Process
- 스캔 데이터를 처리하고 최종 모델을 수신하는 단계.
- RoomBuilder 클래스를 사용해 스캔한 데이터를 처리하고 최종 3D 모델을 생성한다.
- 캡처한 데이터를 처리하는 첫 단계는 ViewController 클래스의 RoomBuilder 인스턴스를 시작하는 것이다.
- 다음은 캡처 과정 이후 센서 데이터를 수신하기 위해 captureSession(_ session: didEndWith data: error:) 메서드를 구현해야 한다.
- stop() 메서드가 호출되거나 에러 발생으로 인해 RoomCaptureSession이 멈추면, 이 함수는 CapturedRoomData object나 에러를 반환하기 위해 호출된다.
- 마지막으로 캡처한 데이터를 처리하기 위해 roomBuilder의 비동기 메서드 roomModel(from:)을 await으로 호출한다.
- 스캔한 데이터를 처리하고 최종 3D 모델을 구축하기 위해 비동기로 실행된다.
- 비동기 함수가 완료되면 최종 모델을 받을 수 있다.
Export
- CapturedRoom 데이터 구조에 대한 세부 사항을 알아보고
- 앱에서 사용할 수 있도록 출력 USD 파일을 생성하고 내보낼 수 있는 방법을 알아본다.
- 최상위 레벨에는 CapturedRoom이 있다.
- 이 CapturedRoom은 Surface와 Object로 구성되어 있다.
- Surface는 curve, edge, 그리고 건축 category로 구성되어 있다.
- Object는 가구 category로 구성되어 있다.
- Surface와 Object는 dimensions(치수), confidence(스캔한 표면 또는 물체에 대한 세 단계의 신뢰도), transform(3D 변형 매트릭스), 그리고 identifier(고유 식별자)와 같은 공통 속성을 몇 가지 공유한다.
- CapturedRoom 구조체는 방의 요소를 온전히 매개변수로 표현한다.
- 처음 4개 요소인 walls, doors, windows, openings는 2D 평면 건축 구조인 Surface 구조를 대표한다.
- Surface 구조체를 보면 앞서 말한 Surface의 속성들이 정의되어 있는 것을 확인할 수 있다.
- CapturedRoom에 정의된 마지막 요소는 Object이며, Object 구조체도 마찬가지이다.
- RoomPlan에서 지원하는 Object 타입.
- export 메서드로 방을 캡처한 데이터인 이 CapturedRoom 구조체를 USD나 USDZ 파일로 내보낼 수 있다.
- 내보낸 USD/USDZ 파일을 C4D같은 프로그램에서 바로 열 수 있다.
- 방의 요소를 온전히 매개변수로 표현하기 때문에 이렇게 스캔 결과가 한 덩어리(mesh)로 저장되지 않고 인식한 카테고리가 USD/USDZ 파일에도 구분되어 있는 것을 확인할 수 있다.
- 따라서 각 카테고리별로 3D 모델을 수정할 수 있다.
Best practices
Roomplan에서 좋은 결과를 얻을 수 있도록 보여주는 몇 가지 모범 사례들.
Recommended conditions
- Single residential rooms
- 일반적인 가정의 가장 일반적인 구조와 물체
- Room size: 최대 9m x 9m
- Lighting: 최소 50 lux
- 일반적인 가정의 밤일 때 조도가 보통 이정도이다.
- 하드웨어: LiDAR가 있는 아이폰, 아이패드
Room selection
스캔이 어려운 조건들.
- Full-height mirrors or glass
- High ceilings
- Dark surfaces
모두 LiDAR가 스캔하기 힘들어하는 조건들이다.
Scanning considerations
더 나은 스캔 결과를 얻기 위해 고려할 사항들.
- 사전준비
- 커튼 열어놓기
- 문 닫아놓기
- 스캔 도중 나오는 질감, 거리, 속도나 조명 조건 등에 대한 지시 따르기
Thermal considerations
스캔이 어려운 조건들.
- 반복적인 스캔
- 5분이 넘어가는 스캔
배터리가 방전되고 발열 떄문에 앱의 사용자 경험에 영향을 줄 수 있다.






























