Как добавить узел в мою сцену 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 ответ
Я что-то упускаю или вы просто хотите, чтобы каждая модель имела одинаковую ориентацию, независимо от ориентации камеры?
В каком случае вы можете просто установить ориентацию каждой модели на ту же, что и для узла, добавленного в начале работы сеанса?
Т.е. когда начинается сеанс, вы добавляете узел к сцене (видимый или скрытый), сохраняете его ориентацию, а затем снова используете его?