1

I'm writing an app that uses the RoomPlan APIs, which works great. But it seems the view after the scan that lets you see the scan in 3-D space can only appear after performing the scan. Is there a way to use the CapturedRoom data from a previous scan to instantiate this view again, without having to perform the whole scan again? I can't see to find anything in the API docs that handles this case. Any help would be appreciated.

More info:

The delegate has this contract:

func captureView(shouldPresent roomDataForProcessing: CapturedRoomData, error: Error?) -> Bool {
    return true
}

How can I present the room for processing by pre-seeding with an already existing CapturedRoom object, and skip the scanning part?

Kevin DiTraglia
  • 25,746
  • 19
  • 92
  • 138

1 Answers1

1

I'm investigating this as well, and don't have an answer on how to use the CapturedRoom struct just yet. Still trying.

As a temporary solution, I export the CapturedRoom struct as a USDZ file and save it in the app's sandbox directory. I then use SceneKit to fetch the newly saved USDZ file and display it as needed. Here's my implementation:

In my RoomCaptureViewController

Note: This is a modified version of the RoomPlan sample code on Apple's Developer website: https://developer.apple.com/documentation/roomplan/create_a_3d_model_of_an_interior_room_by_guiding_the_user_through_an_ar_experience

...
@IBAction func exportResults(_ sender: UIButton) {
   let destinationFolderURL = FileMnager.default.temporaryDirectory.appending(path: "Export")
   let destinationURL = destinationFolderURL.appending(path: "room.usdz")
   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: .mesh)
            
      onDismiss?([destinationURL, capturedRoomURL])
            
      self.dismiss(animated: true)
  } catch {
      print("Error = \(error)")
  }
}
...

I'm using a closure to show the USDZ file in my previous view, hence the onDismiss(?[destinationURL, capturedRoomURL]). In which I use the destinationURL as follows:

import SceneKit
...
....
    private func displayUSDZFile(_ usdzFileURL: URL) {
        let sceneView = SCNView(frame: roomScanView.bounds)
        roomScanView.addSubview(sceneView)
        
        let fileURL = usdzFileURL
        
        // Load the USDZ file using the URL
        do {
            let scene = try SCNScene(url: fileURL, options: nil)

            // Create a SCNNode to hold the 3D content and add it to the scene
            let rootNode = SCNNode()
            for childNode in scene.rootNode.childNodes {
                rootNode.addChildNode(childNode)
            }
            scene.rootNode.addChildNode(rootNode)

            // Set the created scene as the scene property of the SCNView
            sceneView.scene = scene

            // Optionally, configure the scene view properties
            sceneView.autoenablesDefaultLighting = true
            sceneView.allowsCameraControl = true

        } catch {
            print("Failed to load the USDZ file: \(error)")
        }
    }
...
..
  • Update, it looks like we're going to have this option available on iOS 17: https://developer.apple.com/documentation/roomplan/capturedroom/export(to:metadataurl:modelprovider:exportoptions:) I have yet to download the beta, but it looks like we'll have a nicer way of doing this soon! – Juan A. Reyes Jun 30 '23 at 21:30