2014-06-19 21 views
5

Quaternion có thể mô tả không chỉ xoay, mà còn là một định hướng, tức là xoay từ vị trí ban đầu (số không).Xoay trơn tru với quaternions

Tôi muốn mô hình xoay trơn tru từ hướng này sang hướng khác. Tôi đã tính định hướng bắt đầu startOrientation và hướng kết thúc endOrientation và muốn mô tả định hướng trung gian là startOrientation*(1-argument) + endOrientation*argument trong khi argument thay đổi từ 0 thành 1.

Mã cho chức năng cập nhật cơ khỉ là sau:

@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; 
       } 
      } 
     } 


    } 

Công thức cosin đã được dự kiến ​​để mô hình mịn tăng tốc ngay từ đầu và giảm tốc ở cuối.

Mã hoạt động nhưng không như mong đợi: vòng quay trơn tru bắt đầu và kết thúc lâu trước khi các giá trị fractionargument đạt được 1 và tôi không hiểu, tại sao.

Tại sao giá trị orientation đạt đến endOrientation quá nhanh?

Trả lời

4

Bạn đã tuyên bố rằng trong trường hợp của bạn startOrientation đang được sửa đổi. Tuy nhiên; sau vẫn còn đúng

Interpolating giữa quaternion

Phương pháp slerp được bao gồm trong lớp toán qua tec non cho mục đích này: interpolating between two rotations.

Giả sử chúng ta có hai quaternion startOrientationendOrientation và chúng tôi muốn điểm interpolation giữa họ sau đó chúng tôi nội suy từ đó bằng cách sử dụng mã sau:

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

Tại sao cách tiếp cận của bạn có thể nguy hiểm

Quaternions hơi phức tạp trong nội bộ và tuân theo các quy tắc toán học hơi khác nhau để nói vectơ. Bạn đã gọi phương thức multiply(float scalar) trên quaternion. Nội bộ này trông như thế này

public QuaternionD mult(float scalar) { 
     return new QuaternionD(scalar * x, scalar * y, scalar * z, scalar * w); 
} 

Vì vậy, nó chỉ đơn giản nhân tất cả các yếu tố. Điều này rõ ràng không trả về số chuyển đổi scalar lần kích thước. Trong thực tế, một quaternion không còn đại diện cho một vòng quay hợp lệ ở tất cả vì nó không còn là một quaternion đơn vị. Nếu bạn gọi là normalise trên quaterion này, nó sẽ ngay lập tức hoàn tác việc mở rộng quy mô. Tôi chắc chắn Quaternion#multiply(float scalar) có một số cách sử dụng nhưng tôi vẫn chưa tìm thấy chúng.

Đó cũng là trường hợp "thêm" quaternions không kết hợp chúng. Trong thực tế, bạn nhân chúng. Vì vậy, kết hợp q1 sau đó q2 thì q3 có thể đạt được như sau:

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

Các cheat sheet là vô cùng hữu ích cho

Formula này vs slerp so

Trong trường hợp của bạn công thức của bạn cho phép nội suy là gần nhưng không khá chính xác.Điều này cho thấy một đồ thị của yaw cho phép nội suy giữa 2 quaternion sử dụng cả hai phương pháp

enter image description here

+0

Rõ ràng 'slerp' cư xử giống như chức năng của tôi: xoay trực quan đạt định hướng thức nhiều trước khi 'interpolation' đạt' 1'. – Dims

+0

Ngoài ra tôi không thấy 'slerp' với mẫu thử nghiệm của bạn: it void hoặc takes 3 quaternions. – Dims

+0

@Dims Bạn đúng về chữ ký phương thức slerp. Có vẻ một số tài liệu trên JMonkey đã lỗi thời, đã chỉnh sửa. –

Các vấn đề liên quan