Quaternion cube rotation animation

I created this Rubiks Cube with Papervison3D. With some resources I created a Cube with 27 minicubes inside (3*3*3 = 27). Rotating the Rubiks Cube on mouse move is already done. (I do not rotate the camera.)

All the behavior of a Rubiks Cube is in there already. But I'm a bit stuck in the final phase.

When I play with it like I would do with a normal Rubiks Cube it's working ok, besides I know that the default Euler rotation values aren't reliable anymore after a while. What I need is to rotate the Rubiks Cube to the selected side and after that rotate the Rubiks Cube over the z-axis so the minicube face faces up. I prefer to animate it with TweenMax but I'm really stuck since I need quaternion rotations.

I know the selected face of the Rubiks Cube itself. I know the Euler rotation of the Rubiks Cube using Matrix3D.matrix2euler(_rubiksCube.transform); What I need is to rotate it to the selected face for instance when the current rotation is x: -20, y: 35, z: 10 and I select the back face of the rubiksCube it must rotate to x:0, y: 180, z: 0 .

What I need is to change this to Quaternion values and rotate the Rubiks Cube to the new Quaternion value. After that it must rotate the Rubiks Cube over it's z axis to face the selected minicube face up.

This is the code I use when dragging/ rotating the 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;
}

Quaternions are definitely the way to go. It's been a while since I used PV3D, but it goes something like this:

  • Store the euler angles in separate variables (eg, u, v, w). Accumulate these variables in the calculation.
  • Create a quaternion using Quaternion.createFromEuler();
  • Transform using 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;
    }
    

    Update: Ah, I read your question again. It sounds like you want to smoothly interpolate from the current orientation to the new orientation. What worked for me before is this:

  • Get your current euler position and convert to a quaternion using Quaternion.createFromEuler().
  • Get the destination quaternion.
  • Interpolate over time from the source quaternion to the target using 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;
        }
    }
    
    链接地址: http://www.djcxy.com/p/81848.html

    上一篇: PyOpenGL多维数据集映射纹理

    下一篇: 四元数多维数据集旋转动画