Как направить камеру к точке SCNVector3 под iOS 11 - PullRequest
0 голосов
/ 04 октября 2018

Я только начал учиться использовать SceneKit вчера, так что я могу получить некоторые вещи неправильно или неправильно.Я пытаюсь заставить мой cameraNode смотреть на SCNVector3 точку на сцене.

Я пытаюсь сделать мое приложение доступным для людей ниже iOS 11.0.Однако функция look(at:) предназначена только для iOS 11.0+.

. Вот моя функция, в которой я инициализирую камеру:

func initCamera() {
    cameraNode = SCNNode()
    cameraNode.camera = SCNCamera()
    cameraNode.position = SCNVector3(5, 12, 10)
    if #available(iOS 11.0, *) {
        cameraNode.look(at: SCNVector3(0, 5, 0)) // Calculate the look angle
    } else {
        // How can I calculate the orientation? <-----------
    }
    print(cameraNode.rotation) // Prints: SCNVector4(x: -0.7600127, y: 0.62465125, z: 0.17941462, w: 0.7226559)
    gameScene.rootNode.addChildNode(cameraNode)
}

Ориентация SCNVector4(x: -0.7600127, y: 0.62465125, z: 0.17941462, w: 0.7226559) в градусах равна x: -43.5, y: 35.8, z: 10.3 и я не понимаю w.(Кроме того, почему не z = 0? Я думал, что z был рулон ...?)

Вот мои разработки для воссоздания того, что я думал, Угол Y должно быть:

enter image description here

Итак, я решил, что это будет 63.4 degrees, но возвращаемое вращение показывает, что оно должно быть 35.8 degrees.Что-то не так с моими вычислениями, я не полностью понимаю SCNVector4, или есть другой способ сделать это?

Я посмотрел на Подробно объясняя метод ScnVector4 для чего SCNVector4 есть, но я до сих пор не понимаю, для чего w.В нем говорится, что w - это «угол поворота», который, как я думал, был для меня X, Y и Z.


Если у вас есть какие-либо вопросы, пожалуйста, задавайте!

Ответы [ 2 ]

0 голосов
/ 05 октября 2018

Хотя @ rickster дал объяснения свойств узла, я нашел метод, позволяющий вращать узел, чтобы посмотреть на точку с использованием математики (тригонометрия).

Вот мой код:

// Extension for Float
extension Float {
    /// Convert degrees to radians
    func asRadians() -> Float {
        return self * Float.pi / 180
    }
}

, а также:

// Extension for SCNNode
extension SCNNode {
    /// Look at a SCNVector3 point
    func lookAt(_ point: SCNVector3) {
        // Find change in positions
        let changeX = self.position.x - point.x // Change in X position
        let changeY = self.position.y - point.y // Change in Y position
        let changeZ = self.position.z - point.z // Change in Z position

        // Calculate the X and Y angles
        let angleX = atan2(changeZ, changeY) * (changeZ > 0 ? -1 : 1)
        let angleY = atan2(changeZ, changeX)

        // Calculate the X and Y rotations
        let xRot = Float(-90).asRadians() - angleX // X rotation
        let yRot = Float(90).asRadians() - angleY // Y rotation
        self.eulerAngles = SCNVector3(CGFloat(xRot), CGFloat(yRot), 0) // Rotate
    }
}

И вы вызываете функцию, используя:

cameraNode.lookAt(SCNVector3(0, 5, 0))

Надеюсь, это поможет людям в будущем!

0 голосов
/ 05 октября 2018

Существует три способа выразить трехмерное вращение в SceneKit:

  1. На бумаге вы рассчитываете отдельные углы вокруг осей x, y и z.Они называются углами Эйлера , или тангажом, рысканием и креном.Вы можете получить результаты, которые больше похожи на ваши ручные вычисления, если вы используете eulerAngles или simdEulerAngles вместо `вращения.(Или нет, потому что одна из трудностей системы углов Эйлера заключается в том, что вы должны применять каждое из этих трех вращений в правильном порядке.)

  2. simdRotation или rotation использует четырехкомпонентный вектор (float4 или SCNVector4), чтобы выразить представление угла оси поворота.Это зависит от математики, которая неочевидна для многих новичков в трехмерной графике: результат любой последовательности поворотов вокруг разных осей может быть минимально выражен как одно вращение вокруг новой оси.

    Например, вращение на π / 2 радиана (90 °) вокруг оси z (0,0,1) с последующим вращением на π / 2 вокруг оси y (0, 1,0) имеет тот же результат, что и вращение 2/3 вокруг оси (-1 / √3, 1 / √3, 1 / √3).

    Этогде вы запутались в компонентах x, y, z и w SceneKit rotation vector - первые три компонента - это длины, выражающие трехмерный вектор, а четвертый - вращение в радианах вокругэтот вектор.

  3. кватернионы - это еще один способ выразить трехмерное вращение (и тот, который еще дальше от проторенного пути для тех из нас, кто имеет формальное математическое образование, общее дляучебные программы по информатике, но не сумасшедшие продвинутые, либо).У них есть много замечательных функций для 3D-графики, таких как простота компоновки и интерполяции между ними.В SceneKit свойство simdOrientation или orientation позволяет работать с вращением узла в качестве кватерниона.

    Объяснять, как работают кватернионы, слишком много для одного ответа SO, но практическоеВ итоге: если вы работаете с хорошей векторной математикой (например, SIMD-библиотека, встроенная в iOS 9 и более поздние версии ), вы можете в основном рассматривать их как непрозрачные - просто конвертируйте из любого другого представления вращенияпроще всего, и пожинать плоды.

...