Create a 3D View of Your Room Using iOS RoomPlan API
Implement RoomPlan API in your iOS Application.
Powered by ARKit, RoomPlan is a new Swift API that utilizes the camera and LiDAR Scanner on iPhone and iPad to create a 3D floor plan of a room, including key characteristics such as dimensions and types of furniture. ~ Apple
Overview - Dive In
In today's digital age, bringing the physical world into the digital realm has never been easier. RoomPlan, an API powered by ARKit, is designed to revolutionize how we interact with spaces using our iPhones and iPads.
RoomPlan offers a seamless experience, leveraging the power of your device's camera and LiDAR Scanner to create stunning 3D floor plans of rooms in real time. The RoomPlan will work on devices supporting LiDAR with iOS and iPadOS 16.0+.
LiDAR is available on the Pro and Pro Max models of iPhone 12, 13, 14, and 15. Third-generation 11-inch and fifth-generation 12.9-inch iPad Pro models from 2020 and later also have LiDAR.
Thanks to LiDAR technology, RoomPlan offers lightning-fast, real-time scanning capabilities. Users can scan their surroundings effortlessly, with built-in coaching UI guiding optimal scans. Visual feedback ensures users know exactly how their scan is progressing.
RoomPlan doesn't just stop at creating 3D floor plans—it goes further by providing detailed USD or USDZ file formats. These files include dimensions for each component recognized in the room, such as walls and furniture types. Plus, users can fine-tune the dimensions and placement of each component using compatible tools like AutoCAD.
Implementation - Let's Get Started
Let's look at the following steps to implement room plan API in your project.
Setting Up Your Project
Begin by creating a new project in Xcode and give it a name that resonates with your app's purpose. Once the project is set up, create a new file named
RoomCaptureViewController.swift
, where all the magic will happen. Also, don't forget to add a button in your main ViewController.swift that will lead users to the RoomCaptureViewController by navigation.Adding Camera Usage Description
It's crucial to inform users how the camera will be used. Open the
Info.plist
file and addNSCameraUsageDescription
. This simple step ensures transparency and builds trust with your users.Creating the RoomCaptureView
In
RoomCaptureViewController.swift
, import RoomPlan and initialize theRoomCaptureView
. This component will handle the scanning process and provide real-time feedback to users.import UIKit import RoomPlan class RoomCaptureViewController: UIViewController, RoomCaptureViewDelegate { private var roomCaptureView: RoomCaptureView! private var roomCaptureSessionConfig: RoomCaptureSession.Configuration = RoomCaptureSession.Configuration() override func viewDidLoad() { super.viewDidLoad() // call this method to setup room capture view setupRoomCaptureView() } private func setupRoomCaptureView() { roomCaptureView = RoomCaptureView(frame: view.bounds) roomCaptureView.delegate = self view.insertSubview(roomCaptureView, at: 0) }
Implementing Delegate Methods
Make your RoomCaptureViewController conform to the
RoomCaptureViewDelegate
protocol. This allows you to receive updates during the scanning process and capture the final results once scanning is complete.// variable to store captured room data private var finalResults: CapturedRoom? ... func captureView(shouldPresent roomDataForProcessing: CapturedRoomData, error: Error?) -> Bool { return true } func captureView(didPresent processedResult: CapturedRoom, error: Error?) { finalResults = processedResult self.exportButton?.isEnabled = true self.activityIndicator?.stopAnimating() } ...
Starting and Stopping the Capture Session
Add methods to start and stop the capture session. These functions ensure smooth operation of the scanning process and manage the session's lifecycle effectively.
// variable to check if scan is in progress private var isScanning: Bool = false ... override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) startSession() } override func viewWillDisappear(_ flag: Bool) { super.viewWillDisappear(flag) stopSession() } private func startSession() { isScanning = true roomCaptureView?.captureSession.run(configuration: roomCaptureSessionConfig) } private func stopSession() { isScanning = false roomCaptureView?.captureSession.stop() }
Adding Control Buttons
Enhance user experience by adding control buttons such as
Cancel
,Done
, andShare
. These buttons allow users to interact with the scanning session effortlessly. Add in Storyboard and create actions and outlets inRoomCaptureViewController.swift
.... @IBOutlet var exportButton: UIButton? @IBOutlet var doneButton: UIButton? @IBOutlet var cancelButton: UIButton? ... @IBAction func doneScanning(_ sender: UIBarButtonItem) { if isScanning { stopSession() } else { cancelScanning(sender) } self.exportButton?.isEnabled = false self.activityIndicator?.startAnimating() } @IBAction func cancelScanning(_ sender: UIBarButtonItem) { navigationController?.dismiss(animated: true) } @IBAction func exportResults(_ sender: UIButton) { let destinationFolderURL = FileManager.default.temporaryDirectory.appending(path: "Export") let destinationURL = destinationFolderURL.appending(path: "Room.usdz") let capturedRoomURL = destinationFolderURL.appending(path: "Room.json") do { try FileManager.default.createDirectory(at: destinationFolderURL, withIntermediateDirectories: true) let jsonEncoder = JSONEncoder() let jsonData = try jsonEncoder.encode(finalResults) try jsonData.write(to: capturedRoomURL) try finalResults?.export(to: destinationURL, exportOptions: .parametric) let activityVC = UIActivityViewController(activityItems: [destinationFolderURL], applicationActivities: nil) activityVC.modalPresentationStyle = .popover present(activityVC, animated: true, completion: nil) if let popOver = activityVC.popoverPresentationController { popOver.sourceView = self.exportButton } } catch { print("Error = \(error)") } } ...
Managing Button Visibility
Dynamically manage the visibility of buttons based on the scanning state. For example, hide the export button while scanning is in progress and show it once the scan is complete.
... private func startSession() { isScanning = true roomCaptureView?.captureSession.run(configuration: roomCaptureSessionConfig) setActiveNavBar() } private func stopSession() { isScanning = false roomCaptureView?.captureSession.stop() setCompleteNavBar() } ... private func setActiveNavBar() { UIView.animate(withDuration: 1.0, animations: { self.cancelButton?.tintColor = .white self.doneButton?.tintColor = .white self.exportButton?.alpha = 0.0 }, completion: { complete in self.exportButton?.isHidden = true }) } private func setCompleteNavBar() { self.exportButton?.isHidden = false UIView.animate(withDuration: 1.0) { self.cancelButton?.tintColor = .systemBlue self.doneButton?.tintColor = .systemBlue self.exportButton?.alpha = 1.0 } }
And, the End. You're successfully implemented RoomPlan in your project.
But wait don't forget to read the closing paragraph and Find the link to complete code below.
Conslusion - Final Step
Now that you've successfully implemented RoomPlan API in your project. Try improving the code and add new features for saving and interacting with the 3D scanned model. Be creative, Happy Coding 👋
Click here to check the complete sample code at Apple Developer Website 🍎
Feel free to ask any of your queries in the comments!!!
Also, check out my last blog "Learn To Use Git & Github: Add Projects To Your Github Repository" by visiting the link below:
https://himanshugoyal.hashnode.dev/learn-to-use-git-github-add-projects-to-your-github-repository
Image in blog cover by Alexandra Gorn on Unsplash