Невозможно повернуть SCNNode в ARKit - PullRequest
2 голосов
/ 03 мая 2019

Я пытаюсь повернуть узел SCNNode по оси Y, чтобы мой узел (стрелка) указывал в правильном направлении.Я хочу сделать навигационное приложение, которое использует ARKit;каждая стрелка должна указывать на следующее местоположение маршрута, который я получил.Поиск маршрута работает правильно.

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

directionNode.rotation = SCNVector4(x:0, y:1:, z:0, w:Float(bearing))

Это не имеет желаемого эффекта.Я также попытался использовать метод runAction, также безрезультатный:

directionNode.runAction(SCNAction.rotateBy(x: 0, y: CGFloat(bearing), z: 0, duration: 0))

Вот код, который позиционирует и масштабирует узлы.

for i in 0...(directionNodes.count - 1) {
    let directionNode = directionNodes[i]
    let translation = MatrixHelper.transformMatrix(for: matrix_identity_float4x4, originLocation: startingLocation, location: directionNode.location)
    let position = SCNVector3.positionFromTransform(translation)
    let distance = directionNode.location.distance(from: startingLocation)
    DispatchQueue.main.async {
        let scale = 100 / Float(distance)
        directionNode.scale = SCNVector3(x: scale, y: scale, z: scale)
        directionNode.anchor = ARAnchor(transform: translation)
        directionNode.position = position
        if (i < (self.directionNodes.count - 1)) {
            // Apply rotation to the arrow
            let successiveStepLocation = self.directionNodes[i + 1].location!
            let bearing = directionNode.location.bearingToLocationRadian(successiveStepLocation)
            // rotate
            directionNode.rotation = SCNVector4(x:0, y:1:, z:0, w:Float(bearing))
        }
    }
}

Все это заключено в транзакцию SCNTransaction.

Может кто-нибудь сказать мне, почему вращение узла не работает?Любая помощь очень ценится.

[EDIT] : я забыл упомянуть, что объект 3D-стрелки, который я пытаюсь вращать, всегда указывает в одном направлении.Даже когда я «хожу вокруг», стрелка всегда указывает (в моем случае) влево.Может быть, это поможет решить мою проблему ...

Ответы [ 2 ]

0 голосов
/ 04 мая 2019

Большое спасибо за ответ, мне очень помогло понимание различных способов вращения.

Однако выясняется, что на узле было ограничение:

let billboardConstraint = SCNBillboardConstraint()
billboardConstraint.freeAxes = SCNBillboardAxis.Y
constraints = [billboardConstraint]

Комментирование этого кода заставило вращение работать правильно. Довольно тупой ...

Согласно документации SCNBillboardConstraint заставляет ось z объекта всегда указывать на узел pointOfView. Но я не совсем понимаю свойство freeAxes здесь. Тип по умолчанию - all, поэтому он никогда не поворачивается относительно точки зрения. Так что, если я установлю только тип ограничения Y, я могу применить вращение только по осям X и Z? Или я здесь не прав?

0 голосов
/ 03 мая 2019

Обновление: Я считаю, что проблема в singleSided шейдере, который вы используете.Вы видите невидимую сторону вашей модели.Просто включите doubleSided материал для вашей геометрии:

directionNode.geometry?.firstMaterial?.isDoubleSided = true

Вам необходимо использовать значения, выраженные в радианах (эффективный диапазон от -6.28 до +6.28).

Важно, в каком направлении вращается ваш объект >> CW или CCW.Вы не можете видеть геометрию single-sided ( под определенным углом ) при положительном угле поворота +.pi.

Это работаетпуть:

myNode.rotation = SCNVector4(x: 0, y: 1, z: 0, w: (-.pi * 3) / 2)

... и когда вы используете SCNAction, тоже (и не забудьте назначить продолжительность):

let action = SCNAction.repeatForever(SCNAction.rotate(by: -.pi, 
                                                  around: SCNVector3(0,1,0), 
                                                duration: 1.75))
myNode.runAction(action)

... и когда выВы также используете SCNTransaction:

let previousTransform = myNode.transform
let rotate = SCNMatrix4MakeRotation(0, 1, 0, (-Float.pi/2))

SCNTransaction.begin()
SCNTransaction.animationDuration = 3.75
myNode.transform = SCNMatrix4Mult(rotate, previousTransform)
SCNTransaction.commit()

enter image description here

Надеюсь, это поможет.

...