Держите оси X и Z узла параллельно земле, поворачивая ось Y к камере - PullRequest
0 голосов
/ 25 мая 2018

Я пытаюсь держать SCNNode всегда на расстоянии одного метра от передней части камеры и манипулировать узлом так, чтобы оси X и Z всегда были параллельны земле, в то время как узел вращается вокруг оси Y так,что узел всегда обращен к камере.

Приведенный ниже код по большей части достигает моей цели, но при повороте на 90 ° по часовой стрелке или против часовой стрелки узел начинает поворачиваться.Как я могу это исправить?

override func viewDidLoad() {
    super.viewDidLoad()

    boxParent.position = (sceneView.pointOfView?.position)!
    boxParent.orientation = (sceneView.pointOfView?.orientation)!
    boxParent.eulerAngles = (sceneView.pointOfView?.eulerAngles)!
    sceneView.scene.rootNode.addChildNode(boxParent)

    boxOrigin.position = SCNVector3(0,0,-1)
    boxParent.addChildNode(boxOrigin)

    box = SCNNode(geometry: SCNBox(width: 0.5, height: 0.2, length: 0.3, chamferRadius: 0))
    box.geometry?.firstMaterial?.diffuse.contents = UIColor.blue
    box.position = SCNVector3(0,0,0)
    boxOrigin.addChildNode(box)
}
    func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    boxParent.eulerAngles = (sceneView.pointOfView?.eulerAngles)!
    boxParent.orientation = (sceneView.pointOfView?.orientation)!
    boxParent.position = (sceneView.pointOfView?.position)!

    box.position = boxOrigin.worldPosition
    box.eulerAngles.y = (sceneView.pointOfView?.eulerAngles.y)!
    print(box.eulerAngles)

    sceneView.scene.rootNode.addChildNode(box)
}

1 Ответ

0 голосов
/ 25 мая 2018

Вы одновременно используете два типа вращения.Это не правильно!

boxParent.orientation = (sceneView.pointOfView?.orientation)! //quaternion

Эта переменная использует ориентацию узла, выраженную как quaternion (4 компонента: x, y, z, w).

boxParent.eulerAngles = (sceneView.pointOfView?.eulerAngles)!

Вращение узла, выраженное в шагеуглы поворота, рыскания и крена в радианах (3 компонента: x, y, z).

Вам необходимо решить, какую переменную вы будете использовать: orientation или eulerAngles.Я полагаю, вы выберете ориентация .

Читать эту полезную статью и эту о Quaternions и что такое Gimbal Lock is.

Также используйте объект SCNLookAtConstraint (отрицательная ось z узла указывает на целевой узел ограничения) или SCNBillboardConstraint объект (автоматически настраивает ориентацию узла, так что его локальная ось z всегда указываетв направлении узла pointOfView) для автоматической настройки ориентации узла, поэтому камера всегда будет указывать на другой узел.

...