0

I am developing a simple AR app, where the user can:

  • select an object to add to the world from a list of objects
  • manipulate the object, changing its position, its orientation and its scale
  • remove the object
  • save all the objects added and modified as an ARWorldMap
  • load a previously saved ARWorldMap

I'm having some problems in getting the situation as it was before, when the user wants to load the previously saved ARWorldMap. In particular, when I re-add the objects, their positions and orientations are completely different that before.

Here are some details about the app. I initially add the objects as AnchorEntities. Doing some research I found out that the ARWorldMap doesn't save AnchorEntities but only ARAnchors, so I created a singleton object (AnchorEntitiesContainer in the following code) where I have a list of all the AnchorEntities added by the user that gets restored when the user wants to load a saved ARWorldMap.

Here is the initial insertion of objects in the world:

func addObject(objectName: String) {
        let path = Bundle.main.path(forResource: objectName, ofType: "usdz")!
        
        let url = URL(fileURLWithPath: path)
        if let modelEntity = try? ModelEntity.loadModel(contentsOf: url) {
            modelEntity.name = objectName
            modelEntity.scale = [3.0, 3.0, 3.0]
            
            let anchor = AnchorEntity(plane: .vertical, minimumBounds: [0.2, 0.2]) 
            anchor.name = objectName + "_anchor"
            anchor.addChild(modelEntity)
            arView.scene.addAnchor(anchor)
          
            modelEntity.generateCollisionShapes(recursive: true)
        
        }
    }

Here is the saving of the ARWorldMap and of the list of entities added:

    func saveWorldMap() {
        print("Save world map clicked")
       self.arView.session.getCurrentWorldMap { worldMap, _ in
            guard let map = worldMap else {
                self.showAlert(title: "Can't get world map!", message: "Can't get current world map. Retry later.")
                return
            }

            for anchor in self.arView.scene.anchors {
               AnchorEntitiesContainer.sharedAnchorEntitiesContainer().addAnchorEntity(anchorEntity: anchorEntity)
            }
            do {
                let data = try NSKeyedArchiver.archivedData(withRootObject: map, requiringSecureCoding: true)
                try data.write(to: URL(fileURLWithPath: self.worldMapFilePath), options: [.atomic])
            } catch {
                fatalError("Can't save map: \(error.localizedDescription)")
            }
        }
        showAlert(title: "Save world map", message: "AR World Map successfully saved!")
    }

Here is the loading of the ARWorldMap and the re-insertion of the AnchorEntities:

func loadWorldMap() {
        print("Load world map clicked")

        let mapData = try? Data(contentsOf: URL(fileURLWithPath: self.worldMapFilePath))       
        let worldMap = try! NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, from: mapData)
            
        let configuration = self.defaultConfiguration
        configuration.initialWorldMap = worldMap
        self.arView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
                
        for anchorEntity in AnchorEntitiesContainer.sharedAnchorEntitiesContainer().getAnchorEntities()){
            self.arView.scene.addAnchor(anchorEntity)
        }      
    }

The problem is that the position and orientation of the AnchorEntities are completely different than before, so they are not where they should be.

Here are the things I tried:

  • I tried to save ModelEntities instead of AnchorEntities and repeat the initial insertion when loading the saved ARWorldMap but it didn't give the expected results.
  • I thought that maybe the problem was that the world origins are different when the ARWorldMap gets loaded, so I tried to restore the previous world origin but I don't know how to get that information and how to work with it.
  • I noticed that the ARWorldMap has a "center" parameter so I tried to modify the AnchorEntities transform matrix with that information but I never got what I wanted.

So my question is how do I load AnchorEntities into the world in exactly their previous positions and orientations when loading an ARWorldMap?

Jas
  • 21
  • 4

0 Answers0