-->

Can I get 3d models from web servers on Swift?

2020-07-27 02:31发布

问题:

I'm working on an application with Arkit. There are many 3D models and the size is big in my app. Can I get these models out of another server (outside sites)? I'm new on swift, I can't seem to find anything on loading a 3d model from a web server.

is it enough to change the model path there? Thank you

func loadModel() {
    guard let virtualObjectScene = SCNScene(named: "\(modelName).\(fileExtension)", inDirectory: "Models.scnassets/\(modelName)") else {
        return
    }

    let wrapperNode = SCNNode()

    for child in virtualObjectScene.rootNode.childNodes {

        let defaults = UserDefaults.standard
        wrapperNode.addChildNode(child)
    }
    self.addChildNode(wrapperNode)
}

All code:

import UIKit
import SceneKit
import ARKit

class VirtualObject: SCNNode {

    var modelName: String = ""
    var fileExtension: String = ""
    var thumbImage: UIImage!
    var title: String = ""

    var viewController: ViewController?

    override init() {
        super.init()
        self.name = "Virtual object root node"
    }

    init(modelName: String, fileExtension: String, thumbImageFilename: String, title: String) {
        super.init()
        self.name = "Virtual object root node"
        self.modelName = modelName
        self.fileExtension = fileExtension
        self.thumbImage = UIImage(named: thumbImageFilename)
        self.title = title
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func loadModel() {
        guard let virtualObjectScene = SCNScene(named: "\(modelName).\(fileExtension)", inDirectory: "Models.scnassets/\(modelName)") else {
            return
        }

        let wrapperNode = SCNNode()

        for child in virtualObjectScene.rootNode.childNodes {

            let defaults = UserDefaults.standard
            wrapperNode.addChildNode(child)
        }
        self.addChildNode(wrapperNode)
    }

    func unloadModel() {
        self.removeFromParentNode()
        for child in self.childNodes {
                child.removeFromParentNode()
        }
    }

    func translateBasedOnScreenPos(_ pos: CGPoint, instantly: Bool, infinitePlane: Bool) {

        guard let controller = viewController else {
            return
        }

        let result = controller.worldPositionFromScreenPosition(pos, objectPos: self.position, infinitePlane: infinitePlane)

        controller.moveVirtualObjectToPosition(result.position, instantly, !result.hitAPlane)
    }
}

extension VirtualObject {

    static func isNodePartOfVirtualObject(_ node: SCNNode) -> Bool {
        if node.name == "Virtual object root node" {
            return true
        }

        if node.parent != nil {
            return isNodePartOfVirtualObject(node.parent!)
        }

        return false
    }

    static let availableObjects: [VirtualObject] = [
        Anatomy()
    ]
}

回答1:

you can load an scn file from a webserver with ip addresses like this (i used a fake ip below)

let myURL = NSURL(string: “http://110.151.153.202:80/scnfiles/myfile.scn”)

let scene = try! SCNScene(url: myURL! as URL, options:nil)

Edit:

Here’s a simple Swift PlayGrounds which pulls a test cube scn file from my github repo. You just tap anywhere and the cube loads.

import ARKit
import SceneKit
import PlaygroundSupport

class ViewController: NSObject {

      var sceneView: ARSCNView
      init(sceneView: ARSCNView) {
      self.sceneView = sceneView

      super.init()

      self.setupWorldTracking()
      self.sceneView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(ViewController.handleTap(_:))))

}

private func setupWorldTracking() {
    if ARWorldTrackingConfiguration.isSupported {
        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = .horizontal
        configuration.isLightEstimationEnabled = true
        self.sceneView.session.run(configuration, options: [])
    }
}

@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
    }

    // pulls cube.scn from github repo

    let myURL = NSURL(string: "https://raw.githubusercontent.com/wave-electron/scnFile/master/cube.scn")
    let scene = try! SCNScene(url: myURL! as URL, options: nil)
    let node = scene.rootNode.childNode(withName: "SketchUp", recursively: true)
    node?.scale = SCNVector3(0.01,0.01,0.01)

    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!)

 }
}

let sceneView = ARSCNView()

let viewController = ViewController(sceneView: sceneView)
sceneView.autoenablesDefaultLighting = true
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = viewController.sceneView