Анимация вращения куба кватерниона - PullRequest
6 голосов
/ 14 января 2011

Я создал этот кубик Рубикса с Papervison3D.С некоторыми ресурсами я создал куб с 27 миникубами внутри (3 * 3 * 3 = 27).Вращение кубика Рубикса при движении мыши уже сделано.(Я не вращаю камеру.)

Все поведение кубика Рубика уже там.Но я немного застрял на последнем этапе.

Когда я играю с ним, как если бы я играл с обычным кубиком Рубикса, он работает нормально, кроме того, я знаю, что значения вращения Эйлера по умолчанию больше не являются надежнымиспустя некоторое время.Что мне нужно, так это повернуть кубик Рубика в выбранную сторону, а после этого повернуть кубик Рубика по оси z, чтобы поверхность мини-куба была направлена ​​вверх.Я предпочитаю анимировать его с помощью TweenMax, но я действительно застрял, потому что мне нужны кватернионные вращения.

Я знаю выбранное лицо самого кубика Рубика.Я знаю вращение Эйлера кубика Рубика с помощью Matrix3D.matrix2euler(_rubiksCube.transform);. Мне нужно повернуть его на выбранную грань, например, когда текущее вращение x: -20, y: 35, z: 10, и я выбираю заднюю грань куба Рубика, он должен повернуться на x:0, y: 180, z: 0,

Мне нужно изменить это значение на кватернион и повернуть кубик Рубикса на новое значение кватерниона.После этого он должен повернуть кубик Рубика по оси z, чтобы он был направлен к выбранному мини-кубу вверх.

Этот код я использую при перетаскивании / вращении кубика Рубика

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

1 Ответ

4 голосов
/ 31 июля 2011

Кватернионы, безусловно, путь. Прошло много времени с тех пор, как я использовал PV3D, но это выглядит примерно так:

  1. Хранить углы Эйлера в отдельных переменных (например, u, v, w). Накапливайте эти переменные в расчете.
  2. Создать кватернион с помощью Quaternion.createFromEuler ();
  3. Преобразование с использованием quaternion.matrix

Например:

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

Обновление: Ах, я снова прочитал ваш вопрос. Похоже, вы хотите плавно интерполировать от текущей ориентации к новой ориентации. То, что работало для меня раньше, это:

  1. Получите текущую позицию эйлера и конвертируйте в кватернион, используя Quaternion.createFromEuler ().
  2. Получить кватернион назначения.
  3. Выполните интерполяцию во времени от исходного кватерниона к цели с помощью quaternion.slerp ().

Например:

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