【问题标题】:How to load a model and textures from a remote server using ARKit?如何使用 ARKit 从远程服务器加载模型和纹理?
【发布时间】:2019-09-26 02:51:57
【问题描述】:

我正在开发一个在 Xcode 中使用 Swift 的 ARKit 应用程序,试图从远程服务器加载模型,但在将模型和纹理/材质加载在一起并正确显示纹理/材质时遇到问题。

我浏览了一些链接和教程并加载了模型,但没有显示材料。我在场景编辑器中创建了模型,或者下载了它们并转换为 .scn 文件,在 Finder 中找到它们,然后将它们上传到网络服务器。只是 .scn 文件和材料(图片)。

//Tap Gesture 
@objc func handleTap(_ gesture: UITapGestureRecognizer) {

    //hittest
    let results = self.sceneView.hitTest(gesture.location(in: gesture.view), types: ARHitTestResult.ResultType.featurePoint)

    //return first tap
    guard let result: ARHitTestResult = results.first else {
        return
    }

    //Set URL of location of model
    let myURL = NSURL(string: "https://www.website.com/scnfiles/iPhoneX.scn")

    //Try getting this url or return 
    guard let scene = try? SCNScene(url: myURL! as URL, options: nil) else {return}

    //Set the node to be the model
    let node = scene.rootNode.childNode(withName: "SketchUp", recursively: true)

    //Set scale
    node?.scale = SCNVector3(0.025,0.025,0.025)

    //The material image is located in the same directory
    node?.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "https://website/scnfiles/iPhoneX_Screen.jpg")

    //set the position of the model
    let position = SCNVector3Make(result.worldTransform.columns.3.x, result.worldTransform.columns.3.y, result.worldTransform.columns.3.z)
        node?.position = position

    //Add to scene
    self.sceneView.scene.rootNode.addChildNode(node!)
}

我希望模型能够像在本地一样正确加载,显示具有应用纹理的模型,但我得到的模型没有纹理,只有颜色或白色的预期材料。

我收到以下错误,看起来好像是在尝试在本地加载它?

ARKitModels[10386:3406637] [SceneKit] Error: Failed to load : <C3DImage 0x281e45180 src:file:///var/containers/Bundle/Application/233AE78F-748F-420B-96AD-30F591ADF80C/ARKitModels.app/material/iPhoneX_Screen.jpg [0.000000x0.000000]>

感谢您的帮助,如果有更好的方法,请告诉我。谢谢!

【问题讨论】:

    标签: swift arkit


    【解决方案1】:

    所以,由于我想从远程服务器加载所有内容,多亏了@ATV 的帮助,我在本地没有想到任何东西。

    解决方案:循环遍历子节点并将纹理设置为与 node.name 相同的名称。您可以在场景编辑器中设置节点的名称,然后在正确的文件夹中拥有相同名称的图像文件。这允许动态加载。这仅在您可以控制模型/服务器或有明确说明时才有效。

    @objc func handleTap(_ gesture: UITapGestureRecognizer) {
    
        let results = self.sceneView.hitTest(gesture.location(in: gesture.view), types: ARHitTestResult.ResultType.featurePoint)
    
        guard let result: ARHitTestResult = results.first else {
            return
        }
    
        let myURL = NSURL(string: "https://www.website.com/scnfiles/model/model.scn")
    
        guard let scene = try? SCNScene(url: myURL! as URL, options: nil) else {
            return
        }
    
        let node = scene.rootNode.childNode(withName: "SketchUp", recursively: true)
    
        // Solution //
        let children = (node?.childNodes)!
    
        for child in children {
            child.geometry?.materials.forEach{$0.diffuse.contents = "https://www.website.com/scnfiles/model/materials/" + child.name! + ".jpg"
        }
    
        node?.scale = SCNVector3(0.025, 0.025, 0.025)
    
        let position = SCNVector3Make(result.worldTransform.columns.3.x, 
                                      result.worldTransform.columns.3.y, 
                                      result.worldTransform.columns.3.z)
        node?.position = position
        self.sceneView.scene.rootNode.addChildNode(node!)
    }
    

    【讨论】:

    • @ Eric .18 你能告诉我从远程 url 获取模型的格式吗?请分享任何远程 url
    • @ Eric .18 你能告诉我我们如何将 .scn 模式放在服务器端。
    【解决方案2】:

    尝试将预先下载的 UIImage 设置为几何体中所有材质的内容。比如:

    geometry.materials.forEach{$0.diffuse.contents = textureImage}
    

    【讨论】:

    • 谢谢!这如何与所有纹理/在不同表面上具有许多纹理和不同图像的模型一起工作?它只是在所有表面周围放置纹理。
    • 通常,如果您使用多纹理 - 您有以下文件列表: - .obj(或任何模型的格式)具有定义纹理坐标的文件 - .mtl 具有定义材质、照明设置等的文件- 在.mtl 中定义为材质纹理的资源(.jpg、.png)文件您可以阅读更多关于此here
    • @Eric.18 上面列出的所有这些文件都应该位于一个目录中 - 在这种情况下,纹理将自动出现在初始化的 SCNScene 上。
    • 所有文件都在服务器的同一个目录下。纹理未按预期显示。在您的回答中,textureImage 是什么?你以为只把图片和.scn放在同一个目录下就可以不设置任何素材就显示出来吗?我应该以特定方式调用 init SCNScene 吗?
    • @Eric.18 “应该位于一个目录中” - 我的意思是在本地电话上,而不是在服务器上。作为第一步 - 您应该下载(例如使用URLSession.shared.downloadTask...)模型和纹理文件并将它们保存到本地存储(例如使用FileManager.defaultNSTemporaryDirectory())。在此之后,您应该通过将 URL 传递给 local 模型来启动您的 SCNScene。纹理应出现在模型上,无需手动设置。
    猜你喜欢
    • 2021-02-07
    • 2018-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-24
    相关资源
    最近更新 更多