2017-02-15 17 views
0

Для этого, чтобы это было просто, я буду использовать углы и градусы Эйлера.Интерполяция вращения со временем

Скажем, у меня есть угол 45 градусов. И я хочу изменить угол до 315 с течением времени. Для достижения целевого угла нужно взять кратчайший путь. Этот случай выше кратчайшего пути включал бы пройти через 0 градусов, чтобы добраться до 315. У меня уже есть основа для функции ниже. Это, однако, не будет работать для углов.

public static final float approach(float current, float goal, float delta) { 

    final float difference = goal - current; 

    if (difference > delta) return current + delta; 
    if (difference < -delta) return current - delta; 

    return goal; 

} 

Вот изображение, чтобы проблема казалась более ясной. https://drive.google.com/file/d/0B4AZGzr3HML0cThORExNMHFEYlE/view

ответ

0

Я хочу начать с нуля, чтобы убедиться, что я понимаю, что вы просите.
Таким образом, для параметра

 approach()
параметр «ток» обозначает текущий угол. Параметр «цель» указывает желаемый угол. Параметр «delta» указывает время (предполагая секунды), что угол должен достигнуть «цели».

Теперь, чтобы рассчитать кратчайший путь к углу вы можете просто сделать что-то вроде этого:

if(current + (360 - goal) <= 180) // If goal is 180° away it will rotate to the right automatically. 
    // ... Rotate to the right 
else 
    // ... Rotate to the left 

Мы можем проверить, что на самом деле работает, потому что если мы примем ваши требуемые значения (текущего = 45, цель = 315) и выполнить расчет выше, мы должны повернуть направо.

45 + (360 - 315) <= 180 
45 + 45 <= 180 
90 <= 180, true. 
We turn it right. 

Теперь это всего лишь вопрос расчета количества вращения на основе дельта. Это довольно просто.
Я объявлю «totalAngle» в качестве переменной, чтобы отслеживать разницу между текущим углом и углом назначения. Я буду назначать эту переменную в блоках кода if/else. Я также объявляю логическое значение, чтобы помочь мне отслеживать, какое направление мне нужно повернуть.

boolean rotateRight; 
float totalAngle; 

if(current + (360 - goal) <= 180) { 
    totalAngle = current + (360 - goal); 
    rotateRight = true; 
} 
else { 
    totalAngle = goal - current; 
    rotateRight = false; 
} 

Теперь при условии, что она вращается один раз в секунду, я возьму totalAngle и разделить его на количество секунд, прошедших (ака параметра «дельта»). Затем я изменяю «текущий» параметр и возвращаю его.

current -= rotateRight ? (totalAngle/delta) : -(total/delta); 

Конечным функция должна выглядеть следующим образом:

public static float approach(float current, float goal, float delta) { 
    boolean rotateRight; 
    float totalAngle; 

    if(current + (360 - goal) <= 180) { 
     totalAngle = current + (360 - goal); 
     rotateRight = true; 
    } 
    else { 
     totalAngle = goal - current; 
     rotateRight = false; 
    } 

    current -= rotateRight ? (totalAngle/delta) : -(totalAngle/delta); 
    return current; 
} 

Edit: Если кратчайший путь на самом деле самый длинный, предположим, что "ток - (360 - цель) < = 180" является левое вращение, а не правое & наоборот.

+0

Спасибо! Это работает по большей части! Извините, что я не сделал функцию подхода() очень ясной. Дельта-параметр в функции фактически представляет собой количество градусов, которые я хочу вращать в направлении целевого угла. Однако для этой цели вам будет легко приспособиться. – ASasseCreations

+0

Нет проблем! Рад, что смог помочь :) – Nepromine