Анимация вращения куба кватерниона

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

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

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

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

Мне нужно изменить это на значения Quaternion и повернуть кубик Рубика на новое значение Quaternion. После этого он должен повернуть кубик Рубика по оси 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;
}

person Jos Koomen    schedule 14.01.2011    source источник
comment
Я пытался следить за вашим вопросом, но это сложно. Не могли бы вы пояснить, что вам нужно? P.S. Я не флеш-программист. Что вы имеете в виду, что значения вращения Эйлера по умолчанию через некоторое время становятся ненадежными? Я подозреваю, что вы хотите сохранить внутреннее логическое представление кубика рубика, а не их физическое расположение.   -  person Hamish Grubijan    schedule 15.01.2011


Ответы (1)


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

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

Eg:

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 ().

Eg:

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;
    }
}
person Luke Van In    schedule 30.07.2011