如何在SwiftUI应用中保存和加载ARWorldMap?

如何解决如何在SwiftUI应用中保存和加载ARWorldMap?

我遵循了YouTube教程,其中介绍了如何在SwiftUI中放置虚拟模型。

现在我可以放置模型了,我想保存和加载模型位置。

我已经制作了2个用于保存和加载的按钮,但是我不知道正确的代码来保存和加载实体和锚点。

以下代码位于我的updateUIView函数内部:

func updateUIView(_ uiView: ARView,context: Context) {

    if let name = self.modelName {
              
        print("Modell mit dem Namen \(name) wurde zum plaziert")
                  
         let filename = name + ".usdz"
         let modelEntity = try! ModelEntity.loadModel(named: filename)
              
         modelEntity.generateCollisionShapes(recursive: true)
         uiView.installGestures(.all,for: modelEntity)                  
              
         let anchorEntity = AnchorEntity(plane: .any)
         anchorEntity.addChild(modelEntity)
              
         uiView.scene.addAnchor(anchorEntity)            
    }
}

我尝试了一个“ else”语句,因为我一开始就有“ if”。但这没有解决。我做了一个状态变量(布尔型),当我按下保存或加载按钮时触发。但我无法正确连接到updateUIView-function。

更新1:

我在“ updateUIView”函数中实现了保存和加载函数,如下所示:

struct ARViewContainer: UIViewRepresentable {
    
    @Binding var reset: Bool
    @Binding var modelSelector: String
    @Binding var save: Bool
    @Binding var load: Bool

    let config = ARWorldTrackingConfiguration()


    
    
    
    
    func makeUIView(context: Context) -> ARView {
        
        
        
        // create config for all entities
        
        
         let arView = ARView(frame: .zero)


            config.planeDetection = [.horizontal,.vertical]
            config.environmentTexturing = .automatic
            config.sceneReconstruction = .mesh
        
        
        
        arView.session.run(config)
        
        
        
        return arView
        
    }
    

    
    
    // App kontinuierlich beobachten
    func updateUIView(_ uiView: ARView,context: Context) {
        
        
        // create anchor and model-Entity
        if modelSelector != "default" {
            
            let modelEntity = try! ModelEntity.loadModel(named: "\(modelSelector)")
            modelEntity.name = ("\(modelSelector)")
            modelEntity.generateCollisionShapes(recursive: true)
            uiView.installGestures(.all,for: modelEntity)
            let anchor  = AnchorEntity(plane: .any)
            anchor.addChild(modelEntity)
                
            uiView.scene.addAnchor(anchor)
            
        }
    // reset anchor
    if reset == true {
        
        uiView.scene.anchors.removeAll()
        
        }
      
        //MARK: saveload
            if save == true {
            uiView.session.getCurrentWorldMap { (worldMap,_) in
                
                if let map: ARWorldMap = worldMap {
                    
                    let data = try! NSKeyedArchiver.archivedData(withRootObject: map,requiringSecureCoding: true)
                    
                    let savedMap = UserDefaults.standard
                    savedMap.set(data,forKey: "WorldMap")
                    savedMap.synchronize()
                }
            }
        }
        
        if load == true {
            let storedData = UserDefaults.standard

                if let data = storedData.data(forKey: "WorldMap") {

                    if let unarchiver = try? NSKeyedUnarchiver.unarchivedObject(
                                           ofClasses: [ARWorldMap.classForKeyedUnarchiver()],from: data),let worldMap = unarchiver as? ARWorldMap {

                            config.initialWorldMap = worldMap
                            uiView.session.run(config)
                    }
                }
            }
        
            //MARK:
        }

    
}

通过直接将代码编写到updateUIView函数中,我可以使用uiView代替arView。只有config常量必须在makrUIView函数之外。 当我按下相应的按钮时,用于加载和保存的布尔值设置为false,但将为true:

struct SaveLoadReset: View {

    @Binding var reset: Bool
    @Binding var save: Bool
    @Binding var load: Bool
    @Binding var modelSelector: String
    
    var body: some View {
        
            
            
    //HStack für den Laden und Speichern Knopf
                    HStack(spacing: 10){
        
    //save-Button:
                        Button(action: {
                            print("DEBUG: saveButton")
                            self.modelSelector = "default"
                            self.save = true
                            print("DEBUG: save = \(self.save)")
                        })
                        {
                            Image(systemName: "square.and.arrow.up")
                                
                            .padding(20)
                            .background(Color.white)
                            .opacity(0.3)
                            .cornerRadius(20)
                            .padding(10)
                            .font(.title)
                        }
                            
                        
                        
    //load-Button:
                        Button(action: {
                            print("DEBUG: loadButton")
                            self.load = true
                            print("DEBUG: load = \(self.load)")
                        })
                        {
                            Image(systemName: "square.and.arrow.down")
                                
                            .padding(20)
                            .background(Color.white)
                            .opacity(0.3)
                            .cornerRadius(20)
                            .font(.title)
                        }
                        
                        

                        Spacer()
                        
    //reset-Button:
                        Button(action: {
                            
                            print("DEBUG: removeButton")
                            self.reset = true
                            
                            print("DEBUG: reset = \(self.reset)" )
                            
                            
                        })
                        {
                            Image(systemName: "arrow.clockwise.circle")
                                
                            .padding(20)
                            .background(Color.white)
                            .opacity(0.3)
                            .cornerRadius(20)
                            .font(.title)
                            .padding(10)
                        }
                        
                    }
    }
}

到目前为止,我还没有收到任何错误消息,但是我的代码似乎无法正常工作。 我可以按按钮,但是重新启动应用程序后,不会重新加载模型和锚点。

解决方法

您的代码可能如下所示:

import RealityKit
import SwiftUI
import ARKit

struct ARViewContainer: UIViewRepresentable {

    @Binding var saved: Bool
    @Binding var loaded: Bool
    
    let anchor = AnchorEntity(world: [0,-2])
    let arView = ARView(frame: .zero)
    let config = ARWorldTrackingConfiguration()
    
    func makeUIView(context: Context) -> ARView {
        
        let sphere = MeshResource.generateSphere(radius: 1)
        let sphereEntity = ModelEntity(mesh: sphere)
        sphereEntity.name = "SPHERE"
        sphereEntity.setParent(anchor)
        arView.scene.anchors.append(anchor)
        return arView
    }        
    fileprivate func saveWorldMap() {
        print("SAVED")
        DispatchQueue.main.async {
            saved = false
        }
    }
    fileprivate func loadWorldMap() {
        print("LOADED")
        DispatchQueue.main.async {
            loaded = false
        }
    } 
   
    func updateUIView(_ uiView: ARView,context: Context) {
        
        // Retrieve the entity from your scene
        guard let entity = uiView.scene.findEntity(named: "SPHERE")
        else { return }
                        
        if saved {
            self.saveWorldMap()
        }
        if loaded {
            self.loadWorldMap()
        }
    }
}

struct ContentView : View {
    
    @State private var saver = false
    @State private var loader = false
    
    var body: some View {
        VStack {
            ARViewContainer(saved: $saver,loaded: $loader)
            HStack {
                Spacer()
                Button(action: { self.saver.toggle() }) {
                    Text("Save")
                }
                Spacer()
                Button(action: { self.loader.toggle() }) {
                    Text("Load")
                }
                Spacer()
            }
        }
    }
}

saveWorldMap()loadWorldMap()方法的内容可能像这样:

fileprivate func saveWorldMap() {

    arView.session.getCurrentWorldMap { (worldMap,_) in
        
        if let map: ARWorldMap = worldMap {
            
            let data = try! NSKeyedArchiver.archivedData(withRootObject: map,requiringSecureCoding: true)
            
            let savedMap = UserDefaults.standard
            savedMap.set(data,forKey: "WorldMap")
            savedMap.synchronize()
        }
    }
}

fileprivate func loadWorldMap() {

    let storedData = UserDefaults.standard

    if let data = storedData.data(forKey: "WorldMap") {

        if let unarchiver = try? NSKeyedUnarchiver.unarchivedObject(
                               ofClasses: [ARWorldMap.classForKeyedUnarchiver()],from: data),let worldMap = unarchiver as? ARWorldMap {

                config.initialWorldMap = worldMap
                arView.session.run(config)
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-