Как повернуть и заблокировать вращение SCNNode по градусам?

Мне нужно повернуть модель, которую можно свободно вращать, на точные градусы, независимо от того, сколько раз она была повернута.

У меня есть UIPanGestureRecognizer, который свободно вращает 3D-модель вокруг оси Y. Однако я изо всех сил пытаюсь заставить его зафиксироваться в целочисленной степени, когда панорамирование остановлено, и я изо всех сил пытаюсь узнать его вращение в градусах от 0 до 359.

let translation = recognizer.translation(in: self.view)

var newAngleY = Double(translation.x) * (Double.pi) / 180.0
newAngleY += self.currentAngle

self.shipNode?.eulerAngles.y = Float(newAngleY)

if (recognizer.state == .ended)
{
   self.currentAngle = newAngleY
}

Он вращается свободно, но все попытки блокировки с точностью до ближайшего точного градуса и возможность «знать» его угол вращения в диапазоне от 0 до 359.

Я знаю это:

let degrees = newAngleY * ( 180 / Double.pi)

И я знаю, что если градусов > 360, то -= 360 (псевдокод)

Однако, пока UIPanGestureRecognizer делает свое дело, эти проверки, кажется, терпят неудачу, и я не знаю, почему. Это потому, что, когда он все еще панорамируется, вы не можете редактировать частные свойства ViewController?


person SwiftNewbieDoo    schedule 06.06.2019    source источник


Ответы (1)


Вы можете редактировать значение во время выполнения жеста.

Вариантов довольно много, так что это кажется самым простым для начала:

Вы можете попробовать применять эйлера только при изменении состояния И только тогда, когда .x > .x * (некоторое значение, например 1,1). Это обеспечило бы более «привязку к» подходу, например:

 var currentLocation = CGPoint.zero
 var beginLocation = CGPoint.zero

 @objc func handlePan(recognizer: UIPanGestureRecognizer) {
    currentLocation = recognizer.location(in: gameScene)

    var newAngleY = Double(translation.x) * (Double.pi) / 180.0
    newAngleY += self.currentAngle

    switch recognizer.state
    {
     case UIGestureRecognizer.State.began: break
     case UIGestureRecognizer.State.changed:
         if(currentLocation.x > beginLocation.x * 1.1)
         {
           gNodes.bnode.eulerAngles.y = Float(newAngleY)
           beginLocation.x = currentLocation.x
         }
         if(currentLocation.x < beginLocation.x * 0.9) { .etc. }
         break
         case UIGestureRecognizer.State.ended:
           gNodes.bnode.eulerAngles.y = Float(newAngleY)
           break
    }
}

Затем вы можете переключиться на SCNAction (изменив свою математику), чтобы дать больше контроля, например

let vAction = SCNAction.rotateTo(x: 0, y: vAmount, z: 0, duration: 0)
bnode.runAction(vAction)
person Voltan    schedule 12.06.2019