如何将结构或类对象附加到SCNNode

时间:2019-06-23 05:40:27

标签: ios swift scenekit arkit scnnode

我正在尝试创建一个场景,让不同的用户可以显示不同的汽车。当用户首次登录应用程序时,他们会获得uid,用户名等信息。当他们选择汽车时,汽车模型将具有汽车的类型以及用于识别它们的用户对象。

我可以创建一辆汽车,并实施hitTest来找出那辆被挖掘的汽车。我不知道如何为被窃听的汽车分配数据模型,以便知道谁是谁?

到目前为止,我在节点上发现的唯一属性是node.name,我可以将userId附加到该属性上,然后遍历一系列用户以找出谁是谁,但是那不是;如果我有很多用户。删除节点时,我还需要该属性:

sceneView.session.pause()
sceneView.scene.rootNode.enumerateChildNodes { (node, _) in
    // this would actually remove all the ferraries on the scene but this is just an example
    if node.name == "ferrari" {
        node.removeFromParentNode()
    }
}

如何将数据模型附加到SCNNode?

class User {
    var userId: String?
    var username: String?
}

class RaceCar {
    var user: User?
    var type: String?
}

// user creates an account and picks a ferrari

let raceCar = RaceCar()
let type = raceCar.type!

switch type {

    case "ferrari":

        createFerrariAndAddItToScene(raceCar)

    case "bmw":
    ...etc
}

func createFerrariAndAddItToScene(_ raceCar: RaceCar) {

      let image = art.scnassests/"\(raceCar.typ!e).jpg"

      let material = SCNMaterial()
      material.diffuse.contents = image

      let plane = SCNPlane(width: 0.1, height: 0.1)
      plane.materials = [material]

      let node = SCNNode()
      node.name = raceCar.type!
      node.geometry = plane
      node.position = SCNVector(0.0, 0.0, -0.2)

      sceneView.scene.rootNode.addChildNode(node)
}

@objc func nodeWasTapped(_ sender: UITapGestureRecognizer) {

    guard let sceneView = sender.view as? ARSCNView else { return }  
    let touchLocation = sender.location(in: sceneView)

    let hitResults = sceneView.hitTest(touchLocation, options: [:])

    if !hitResults.isEmpty {

        guard let hitResult = hitResults.first  else { return }  
        let node = hitResult.node

        print(node.name) // I need to get some info from the dataModel here like node.raceCar.user.username or node.raceCar.user.userId
    }
}

1 个答案:

答案 0 :(得分:1)

您可以继承SCNNode并为其添加所需的任何数据模型:

class CarNode: SCNNode {
  var raceCar: RaceCar?

  init(raceCar: RaceCar, geometry: SCNGeometry) {
    super.init()

    self.geometry = geometry

    self.raceCar = raceCar
  }

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

要创建新节点,只需使用以下新类:

func createFerrariAndAddItToScene(_ raceCar: RaceCar) {
  ...
  let node = CarNode(raceCar: raceCar, geometry: plane)
  ...
}

要访问数据模型,您可以这样做:

@objc func nodeWasTapped(_ sender: UITapGestureRecognizer) {
  ...
  if let node = hitResult.node as? CarNode {
    print(node.raceCar.user.username)
  }
}