RoomPlan use RoomCaptureView with existing CapturedRoom

683 views Asked by At

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?

1

There are 1 answers

1
Juan A. Reyes On

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)")
        }
    }
...
..