【问题标题】:How do I add a node to my SceneKit/ARKit scene, retaining its position but resetting its orientation/rotation如何将节点添加到我的 SceneKit/ARKit 场景,保留其位置但重置其方向/旋转
【发布时间】:2017-12-05 07:11:09
【问题描述】:

我想在我的场景中添加一个节点,保持相对于相机的位置,但保持场景的方向/旋转。到目前为止我在哪里......

当我点击屏幕时,我会在场景中添加一个锚点,其变换等于相机的变换。然后在didUpdateNode 中,也就是锚节点设置其位置信息时,我添加了一个包含模型的子节点,该模型具有position.z = -0.5。模型节点直接添加到摄像机前面的场景中,并反映摄像机的旋转属性。手机向下倾斜并成一定角度时,可能看起来像这样:

模型节点,受锚节点旋转数据的影响,旋转方式与相机相同。这个特殊的模型出现在它的一边——我不担心,它只是一个占位符。也忽略顶部的红色按钮,用于调试。

到目前为止,一切都很好。

我想要做的是让旋转信息基本上“重置”,因此它会出现在与我的相机相同的高度,并面向默认的正面位置。如果我以不同的方式旋转相机并在房间内移动,则会在不同的位置添加其他模型,但仍保持相同的高度和相同的方向。

这可能看起来像这样。想象一下,我刚刚点击屏幕添加了对象,它以标准高度显示,并且与场景相关,而不是相机旋转。

我尝试过使用节点的eulerAnglesrotationorientation 属性,但无法使其令人满意地工作。这是我到目前为止的代码。我创建了一个空白场景,并使用标准 SceneKit 项目中的ship.scn 作为模型:

class ViewController: UIViewController, ARSCNViewDelegate {
  @IBOutlet var sceneView: ARSCNView!

  var anchors = [ARAnchor]()    

  override func viewDidLoad() {
    super.viewDidLoad()

    // Set the view's delegate
    sceneView.delegate = self

    // Show statistics such as fps and timing information
    sceneView.showsStatistics = true

    // Create a new scene
    let scene = SCNScene(named: "scene.scn")!

    // Set the scene to the view
    sceneView.scene = scene
  }

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // Create a session configuration
    let configuration = ARWorldTrackingSessionConfiguration()
    configuration.planeDetection = .horizontal

    // Run the view's session
    sceneView.session.run(configuration)
  }

  override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    // Pause the view's session
    sceneView.session.pause()
  }

  func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
    if anchors.contains(anchor) {
        // Create a new scene
      let scene = SCNScene(named: "art.scnassets/ship.scn")!
      let shipNode = scene.rootNode.childNode(withName: "ship", recursively: true)!
      shipNode.position.z = -5
      node.addChildNode(shipNode)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)

        if let currentFrame = sceneView.session.currentFrame {
        let translation = matrix_identity_float4x4
        let transform = simd_mul(currentFrame.camera.transform, translation)
        let anchor = ARAnchor(transform: transform)

        anchors.append(anchor)
        sceneView.session.add(anchor: anchor)
        }
    }
  }
}

【问题讨论】:

  • 关于模型位置:您到底想重置什么?你想让飞机出现在你的相机高度吗?在固定的恒定高度?飞机总是出现在你的相机的北边?在镜头前开吗?关于模型方向:你希望它有一个与相机无关的常数(比如总是向北,总是垂直)还是混合(比如总是面向相机,总是垂直)?
  • 也许看看SCNTransformConstraint
  • @Guig 理想情况下,我希望在世界上创建一个平面,其中 z 坐标将从南到北移动,x 坐标从西到东,所以在我的初始节点中我试图创建那。我确实省略了让飞机与北方对齐的细节,因为这涉及核心位置,这是下一步。现在我只需要通俗地说,它是平的且不旋转的,就好像它直接坐在地板上一样。

标签: ios scenekit scnnode arkit arscnview


【解决方案1】:

我是否遗漏了什么,或者您只是希望每个模型具有相同的方向,而不考虑相机方向?

在哪种情况下,您可以将每个模型的方向设置为与会话开始运行时添加的节点相同吗?

即当会话开始时,您将节点添加到场景(可见或隐藏),保存其方向,然后稍后再次使用?

【讨论】:

    猜你喜欢
    • 2017-12-25
    • 2017-12-03
    • 2018-07-19
    • 2019-03-20
    • 2023-03-03
    • 2019-10-06
    • 2018-11-01
    • 2018-08-24
    • 1970-01-01
    相关资源
    最近更新 更多