2014-06-19 15 views
5

Czwartorzędowość może opisywać nie tylko obrót, ale także orientację, tj. Obrót od początkowej (zerowej) pozycji.Płynna rotacja z kwaterami

Chciałem modelować płynne obracanie z jednej orientacji na drugą. Obliczyłem orientację początkową startOrientation i orientację końcową endOrientation i chciałem opisać orientacje pośrednie jako startOrientation*(1-argument) + endOrientation*argument, podczas gdy zmienia się z 0 do.

kod dla funkcji aktualizacji silnika małpa jest następujący: oczekuje

@Override 
    public void simpleUpdate(float tpf) { 

     if(endOrientation != null) { 

      if(!started) { 
       started = true; 
      } 
      else { 

       fraction += tpf * speed; 
       argument = (float) ((1 - Math.cos(fraction * Math.PI))/2); 

       orientation = startOrientation.mult(1-argument).add(endOrientation.mult(argument)); 
       //orientation = startOrientation.mult(1-fraction).add(endOrientation.mult(fraction)); 
       log.debug("tpf = {}, fraction = {}, argument = {}", tpf, fraction, argument); 
       //log.debug("orientation = {}", orientation); 

       rootNode.setLocalRotation(orientation); 

       if(fraction >= 1) { 

        rootNode.setLocalRotation(endOrientation); 
        log.debug("Stopped rotating"); 

        startOrientation = endOrientation = null; 
        fraction = 0; 
        started = false; 
       } 
      } 
     } 


    } 

Wzór cosinus został model gładka przyspieszenie na początku i na koniec zwalnia.

Kod działa, ale nie zgodnie z oczekiwaniami: płynna rotacja zaczyna się i kończy na długo przed osiągnięciem i argument wartości 1 i nie rozumiem, dlaczego.

Dlaczego wartość orientation osiąga wartość endOrientation tak szybko?

Odpowiedz

4

Poinformowałeś, że w twoim przypadku modyfikowano startOrientation. Jednak; dodaje pozostaje prawdą

interpolację między kwaterniony

metody slerp są uwzględnione w klasie quaternion do tego celu: interpolating between two rotations.

Zakładając mamy dwa quaternions startOrientation i endOrientation i chcemy punkt interpolation między nimi potem interpolujemy następnie za pomocą następującego kodu:

float interpolation=0.2f; 
Quaternion result=new Quaternion(); 
result.slerp(startOrientation, endOrientation, interpolation); 

Dlaczego Twoje podejście może być niebezpieczne

Czwartończochy są nieco skomplikowane wewnętrznie i podlegają nieco innym regułom matematycznym, co oznacza wektory. Wywołałeś metodę multiply(float scalar) na kwaternionu. Wewnętrznie wygląda to tak, jakby to było proste mnożenie wszystkich elementów. To wyraźnie nie zwraca wartości o jeden raz większy niż rozmiar. W rzeczywistości taki kwaternion w ogóle nie reprezentuje już prawidłowej rotacji, ponieważ nie jest już kwaternionem jednostkowym. Jeśli zadzwonisz pod numer normalise, natychmiast cofnie to skalowanie. Jestem pewien, że Quaternion#multiply(float scalar) ma jakieś zastosowanie, ale jeszcze ich nie znajduję.

Jest również tak, że "dodawanie" kwaternionów ich nie łączy. W rzeczywistości je pomnażaj. Więc łącząc Q1 a następnie Q2 potem Q3 byłby osiągnięty w sposób następujący:

Quaternion q0 = q1.mult(q2).mult(q3); 

cheat sheet jest niezwykle przydatna dla tej

Formuły vs porównaniu slerp

W twoim przypadku formuła dla interpolacji jest prawie, ale nie całkiem poprawne.To pokazuje wykres odchylenia dla interpolacji między 2 kwaterniony obiema metodami

enter image description here

+0

Widocznie 'slerp' zachowuje się tak samo jak mojej funkcji: rotacja wizualnie osiągnie ostateczną orientację znacznie przed' '1 'interpolation' osiągnie. – Dims

+0

Również nie widzę 'slerp' z twoim prototypem: ani it void, ani takes 3 quaternions. – Dims

+0

@Dims Masz poprawne podpisanie metody slerp. Wydaje się, że niektóre dokumenty JMonkey są nieaktualne, edytowane. –

Powiązane problemy