如何使用ARKit从远程服务器加载模型和纹理?

时间:2019-05-08 11:19:58

标签: swift arkit

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

我已经浏览了一些链接和教程,并加载了模型,但是没有显示材料。我已经在场景编辑器中创建了模型,或者下载了模型并将其转换为.scn文件,在Finder中找到它们,然后将其上传到Web服务器。只是.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]>

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

2 个答案:

答案 0 :(得分:0)

尝试将预下载的UIImage设置为来自几何图形的所有材质的内容。像这样:

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

答案 1 :(得分:0)

因此,由于我想从远程服务器加载所有内容,因此@@@@@@@@@@@@@@@的一些帮助,使我在本地没有想到。

解决方案:遍历子节点并将纹理设置为与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!)

    }