6

このルービックキューブは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;
}
4

1 に答える 1

4

クォータニオンは間違いなく進むべき道です。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;
    }
}
于 2011-07-30T22:26:04.223 に答える