Как добавить узел в мою сцену SceneKit/ARKit, сохранив его положение, но сбросив его ориентацию / вращение

Я хочу добавить узел к моей сцене, сохраняя положение по отношению к камере, но сохраняя ориентацию / поворот сцены. Где я до сих пор...

Когда я касаюсь экрана, я добавляю привязку к моей сцене с преобразованием, равным преобразованию камеры. Затем в didUpdateNode, когда узел привязки имеет свою настройку позиционной информации, я добавляю дочерний узел, содержащий модель, которая имеет position.z = -0.5, Узел модели добавляется к сцене прямо перед камерой и отражает свойства вращения камеры. Если телефон наклонен вниз и под углом, это может выглядеть так:

Узел модели, на который влияют данные вращения узла привязки, поворачивается так же, как и камера. Эта конкретная модель появляется на ее стороне - меня это не касается, это просто заполнитель. Также игнорируйте красную кнопку вверху, которая была для отладки.

Все идет нормально.

Вместо этого я хочу, чтобы информация о вращении по существу "сбрасывалась", поэтому вместо этого она отображается на той же высоте, что и моя камера, и обращена к положению по умолчанию лицом вперед. И если бы я поворачивал камеру по-разному и перемещался по комнате, дополнительные модели были бы добавлены в разных положениях, но все еще на той же высоте и с той же ориентацией.

Это может выглядеть примерно так. Представьте, что я только что нажал на экран, чтобы добавить объект, и он появляется на стандартной высоте, а поворот имеет отношение к сцене, а не к камере.

Я пытался поиграть с узлом eulerAngles, rotation а также orientation свойства, но не могу заставить это работать удовлетворительно. Вот код, который у меня есть до сих пор... Я создал пустую сцену, и я использую ship.scn из стандартного проекта SceneKit в качестве модели:

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

1 ответ

Я что-то упускаю или вы просто хотите, чтобы каждая модель имела одинаковую ориентацию, независимо от ориентации камеры?

В каком случае вы можете просто установить ориентацию каждой модели на ту же, что и для узла, добавленного в начале работы сеанса?

Т.е. когда начинается сеанс, вы добавляете узел к сцене (видимый или скрытый), сохраняете его ориентацию, а затем снова используете его?

Другие вопросы по тегам