2011-01-14 10 views
6

Stworzyłem kostkę Rubiks z Papervison3D. Z pewnymi zasobami stworzyłem Kostkę z 27 minicubami wewnątrz (3 * 3 * 3 = 27). Obracanie kostki Rubiks na ruchy myszy jest już zakończone. (Nie obracam aparatu.)Animacja obrotu kostki czwartorzędowej

Całe zachowanie kostki Rubiks już tam jest. Ale trochę utknąłem w końcowej fazie.

Kiedy gram z nim tak, jak robiłbym normalną kostkę Rubiks, to działa dobrze, poza tym wiem, że domyślne wartości obrotów Eulera nie są już pewne. Potrzebuję obrócić kostkę Rubiks do wybranej strony, a następnie obrócić kostkę Rubiks nad osią Z, tak aby twarz minikanki była skierowana w górę. Wolę animować go za pomocą TweenMax, ale naprawdę utknąłem, odkąd potrzebuję rotacji kwaternionów.

Znam wybraną twarz samej kostki Rubiks. Znam rotację Eulera Kostki Rubiksa używając Matrix3D.matrix2euler(_rubiksCube.transform); Potrzebuję obrócić go do wybranej ściany, na przykład, gdy obecny obrót to x: -20, y: 35, z: 10 i wybieram tylną ścianę rubiksCube, którą musi obrócić do x:0, y: 180, z: 0.

Potrzebuję zmienić to na wartości kwaternionów i obrócić kostkę Rubiks do nowej wartości czwartorzędowej. Następnie musi obracać Rubiks Cube na swojej osi Z, aby zmierzyć się z wybraną minikwarką twarzą do góry.

Jest to kod używam podczas przeciągania/obracanie 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

Starałem się śledzić swoje pytanie, ale trudno. Czy możesz spróbować wyjaśnić, czego potrzebujesz? P.S. Nie jestem programistą flash. Co masz na myśli przez "domyślne wartości rotacji Eulera po pewnym czasie nie są wiarygodne"? Podejrzewam, że chcesz zachować wewnętrzną * logiczną * reprezentację kostki rubika zamiast ich fizycznej lokalizacji. –

Odpowiedz

4

Quaternions są zdecydowanie droga. Minęło trochę czasu odkąd wykorzystywane PV3D, ale to idzie mniej więcej tak:

  1. Store kąty Eulera w oddzielnych zmiennych (np, u, v, w). Skumuluj te zmienne w obliczeniach.
  2. Utwórz kwaternion za pomocą Quaternion.createFromEuler();
  3. Transform użyciu quaternion.matrix

np

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

Update: Ach, znowu czytać swoje pytanie. Wygląda na to, że chcesz płynnie wstawiać interpolację z aktualnej orientacji do nowej orientacji. To, co zadziałało wcześniej, jest następujące:

  1. Zdobądź aktualną pozycję Eulera i przekształć ją w kwaternion za pomocą Quaternion.createFromEuler().
  2. Zdobądź kwaterę docelową.
  3. Interpolować w czasie od źródłowego kwaternionu do celu za pomocą quaternion.slerp().

Np

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