2011-01-14 45 views
6

Tôi đã tạo khối Rubiks này với Papervison3D. Với một số tài nguyên, tôi đã tạo một Cube với 27 minicubes bên trong (3 * 3 * 3 = 27). Xoay khối Rubiks trên di chuyển chuột đã được thực hiện. (Tôi không xoay máy ảnh.)Hoạt hình xoay hình khối Quaternion

Tất cả hành vi của khối Rubiks đã sẵn sàng. Nhưng tôi hơi bị mắc kẹt trong giai đoạn cuối cùng.

Khi tôi chơi với nó như tôi sẽ làm với một Rubiks Cube bình thường nó làm việc ok, bên cạnh đó tôi biết rằng giá trị Euler mặc định xoay không đáng tin cậy nữa sau một thời gian. Những gì tôi cần là xoay khối Rubiks sang phía đã chọn và sau đó xoay khối Rubiks trên trục z để mặt minicube hướng lên trên. Tôi thích làm sống động nó với TweenMax nhưng tôi thực sự bị mắc kẹt vì tôi cần quay vòng quaternion.

Tôi biết khuôn mặt được chọn của khối Rubiks. Tôi biết xoay Euler của Rubiks Cube sử dụng Matrix3D.matrix2euler(_rubiksCube.transform); Điều tôi cần là xoay nó sang mặt được chọn chẳng hạn khi xoay hiện tại là x: -20, y: 35, z: 10 và tôi chọn mặt sau của rubiksCube nó phải xoay đến x:0, y: 180, z: 0.

Điều tôi cần là thay đổi giá trị này thành giá trị Quaternion và xoay khối Rubiks thành giá trị Quaternion mới. Sau đó, nó phải xoay khối Rubiks trên trục z của nó để đối mặt với mặt minicube được chọn.

Đây là mã tôi sử dụng khi kéo/xoay Rubiks Cube

private function onMouseMove(e : MouseEvent) : void { 
    var m : Matrix3D; 
    m = Matrix3D.rotationY((mouseX - _mouseDownPoint.x)/120); 
    m = Matrix3D.multiply(m, Matrix3D.rotationX(-(mouseY - _mouseDownPoint.y)/120)); 
    _rubiksCube.transform = Matrix3D.multiply(m, _rubiksCube.transform); 
    _mouseDownPoint.x = mouseX; 
    _mouseDownPoint.y = mouseY; 
} 
+2

Tôi cố gắng để làm theo câu hỏi của bạn, nhưng nó là khó khăn. Bạn có thể cố gắng rõ ràng hơn về những gì bạn cần không? P.S. Tôi không phải là lập trình viên flash. Bạn có ý nghĩa gì bởi "giá trị xoay Euler mặc định không đáng tin cậy sau một thời gian"? Tôi nghi ngờ rằng bạn muốn giữ một biểu tượng * logic * nội bộ của khối lập phương của rubic thay vì vị trí vật lý của chúng. –

Trả lời

4

Quaternions chắc chắn con đường để đi. Đã lâu rồi kể từ khi tôi sử dụng PV3D, nhưng nó giống như thế này:

  1. Lưu các góc euler trong các biến riêng biệt (ví dụ u, v, w). Tích lũy các biến này trong phép tính.
  2. Tạo một quaternion bằng cách sử dụng Quaternion.createFromEuler();
  3. Chuyển đổi sử dụng quaternion.matrix

Ví dụ:

var yRotation:Number = 0; 
var xRotation:Number = 0; 

function mouseHandler(e:MouseEvent):void { 
    yRotation += (mouseX - _mouseDownPoint.x)/120; 
    xRotation += -(mouseY - _mouseDownPoint.y)/120); 

    var q:Quaternion = Quaternion.createFromEuler(xRotation, yRotation, zRotation, true); 
    _rubiksCube.transform = q.matrix; 
    _mouseDownPoint.x = mouseX; 
    _mouseDownPoint.y = mouseY; 
} 

Cập nhật: Ah, tôi đọc câu hỏi của bạn một lần nữa. Có vẻ như bạn muốn nội suy thông suốt từ hướng hiện tại sang hướng mới. Những gì đã làm việc cho tôi trước đây là:

  1. Lấy vị trí euler hiện tại của bạn và chuyển sang một quaternion bằng cách sử dụng Quaternion.createFromEuler().
  2. Lấy quaternion đích.
  3. Nội suy theo thời gian từ quaternion nguồn đến đích bằng quaternion.slerp().

Ví dụ:

function clickHandler(e:MouseEvent):void { 
    qSource = qCurrent; 
    qTarget = quaternion.createFromEuler(....); 
    t = getTimer(); 
} 

function frameHandler(e:Event):void { 
    if (isAnimating) { 
     tDelta = (getTimer() - t)/10000; // 10000 = 10 seconds 
     qCurrent = slerp(qSource, qTarget, tDelta); 
     _rubiksCube.transform = qCurrent.matrix; 
    } 
}