I am making an app with RoomPlan using the official sample code.
A model of the room is generated as it is scanned, and when the scan is complete, chairs and other objects are aligned parallel to the desk. I wanted to stop this behavior, so I decided to use the option beautifyObjects.
import UIKit
import RoomPlan
class RoomCaptureViewController: UIViewController, RoomCaptureViewDelegate, RoomCaptureSessionDelegate {
@IBOutlet var exportButton: UIButton?
@IBOutlet var doneButton: UIBarButtonItem?
@IBOutlet var cancelButton: UIBarButtonItem?
@IBOutlet var activityIndicator: UIActivityIndicatorView?
private var isScanning: Bool = false
private var roomCaptureView: RoomCaptureView!
private var roomCaptureSessionConfig: RoomCaptureSession.Configuration = RoomCaptureSession.Configuration()
private var roomBuilder: RoomBuilder!
private var processedResult: CapturedRoom?
private var finalResults: CapturedRoom?
override func viewDidLoad() {
super.viewDidLoad()
// Set up after loading the view.
setupRoomBuilder()
setupRoomCaptureView()
activityIndicator?.stopAnimating()
}
private func setupRoomBuilder() {
let beautifyObjectsEnabled = UserDefaults.standard.bool(forKey: "beautifyObjectsEnabled")
if beautifyObjectsEnabled {
roomBuilder = RoomBuilder(options: [.beautifyObjects])
} else {
roomBuilder = RoomBuilder(options: [])
}
}
private func setupRoomCaptureView() {
roomCaptureView = RoomCaptureView(frame: view.bounds)
roomCaptureView.captureSession.delegate = self
roomCaptureView.delegate = self
view.insertSubview(roomCaptureView, at: 0)
}
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)
setActiveNavBar()
}
private func stopSession() {
isScanning = false
roomCaptureView?.captureSession.stop()
setCompleteNavBar()
}
// Decide to post-process and show the final results.
func captureView(shouldPresent roomDataForProcessing: CapturedRoomData, error: Error?) -> Bool {
Task {
do {
let capturedRoom = try await roomBuilder.capturedRoom(from: roomDataForProcessing)
DispatchQueue.main.async {
self.finalResults = capturedRoom
self.exportButton?.isEnabled = true
self.activityIndicator?.stopAnimating()
}
} catch {
print("Error processing room data: \(error.localizedDescription)")
}
}
return true
}
// Access the final post-processed results.
func captureView(didPresent processedResult: CapturedRoom, error: Error?) {
finalResults = processedResult
self.exportButton?.isEnabled = true
self.activityIndicator?.stopAnimating()
}
@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)
}
// Export the USDZ output by specifying the `.parametric` export option.
// Alternatively, `.mesh` exports a nonparametric file and `.all`
// exports both in a single USDZ.
@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)")
}
}
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
}
}
}
The func captureView(shouldPresent roomDataForProcessing: CapturedRoomData, error: Error?) is mainly changed. I have confirmed in the debugger that the roomBuilder options are changed according to the buttons in the UI.
Anyone who knows more about the behavior of this option, please give me an advice.