0

CATransformLayerを使用して6面の3Dダイスを作成しました。これをコンテナレイヤーとして使用して、6つの変換されたレイヤーを空間内で回転できる3Dオブジェクトにグリップします。ここからアイデアを得ました。それはうまく機能しており、最上層でCATransform3DMakeRotationを呼び出す「サイコロ」を回転させることができます。サイコロは回転してうまく機能します。

次のステップは、プログラムに「弾丸物理学」を挿入することでした。私はそれを機能させていますが、物理学の世界のサイコロの「弾丸物理学の「クォータニオン」方向」から、コンテナのCALayerメソッドに渡すことができる回転角に変換する方法がわからないために行き詰まっています。

これが私がしていることです:

1)「弾丸物理学」を呼び出して、サイコロの向きを取得します。

// QUATERNION: Get the orientation
btQuaternion quatO = TObject->getOrientation();

2)クォータニオンをオイラーに変換します(答えをグーグルで検索すると、以下にコピーされたメソッドが見つかりました)qW = quatO.getW(); qX = quatO.getX(); qY = quatO.getY(); qZ = quatO.getZ(); [自己quaternionToEuler];

3)新しいオイラー角をCALayerに適用します(sCtrl)

[sCtrl rotaX:eX rotaY:eY rotaZ:eZ];

注1:これは私のcalayerを回転させるために使用している方法です

- (CATransform3D) rotaX:(CGFloat) anguloX  rotaY:(CGFloat) anguloY rotaZ:(CGFloat) anguloZ
{         
    CATransform3D rX;
    CATransform3D rY;
    CATransform3D rZ;
    CATransform3D ret;

    // Apply all the rotations in order (x, y, z)
    rX = CATransform3DMakeRotation([self gradosARadianes:(anguloX)], 1.0f, 0.0f, 0.0f);
    ret = CATransform3DConcat(baseTransform, rX);
    rY = CATransform3DMakeRotation([self gradosARadianes:(anguloY)], 0.0f, 1.0f, 0.0f);
    ret = CATransform3DConcat(rX, rY);
    rZ = CATransform3DMakeRotation([self gradosARadianes:(anguloZ)], 0.0f, 0.0f, 1.0f);
    ret = CATransform3DConcat(rY, rZ);


    // Store finished result for next time start from there... 
    baseTransform = ret;

    return ret;
}

注2:これは、クォータニオンをオイラーに変換するために私が見つけた方法です。

-(void) quaternionToEuler
{
    float matrix[3][3];
    float cx,sx;
    float cy,sy,yr;
    float cz,sz;
    matrix[0][0] = 1.0f - 2.0f * (qY * qY + qZ * qZ);
    matrix[0][1] = (2.0f * qX * qY) - (2.0f * qW * qZ);
    matrix[1][0] = 2.0f * (qX * qY + qW * qZ);
    matrix[1][1] = 1.0f - (2.0f * qX * qX) - (2.0f * qZ * qZ);
    matrix[2][0] = 2.0f * (qX * qZ - qW * qY);
    matrix[2][1] = 2.0f * (qY * qZ + qW * qX);
    matrix[2][2] = 1.0f - 2.0f * (qX * qX - qY * qY);


    sy = -matrix[2][0];
    cy = sqrt(1 - (sy * sy));
    yr = (float)atan2(sy,cy);
    eY = (yr * 180.0f) / (float)M_PI;

    if (sy != 1.0f && sy != -1.0f)   
    {
        cx = matrix[2][2] / cy;
        sx = matrix[2][1] / cy;
        eX = ((float)atan2(sx,cx) * 180.0f) / (float)M_PI;   // RAD TO DEG

        cz = matrix[0][0] / cy;
        sz = matrix[1][0] / cy;
        eZ = ((float)atan2(sz,cz) * 180.0f) / (float)M_PI;   // RAD TO DEG
    }
    else
    {
        cx = matrix[1][1];
        sx = -matrix[1][2];
        eX = ((float)atan2(sx,cx) * 180.0f) / (float)M_PI;   // RAD TO DEG

        cz = 1.0f;
        sz = 0.0f;
        eZ = ((float)atan2(sz,cz) * 180.0f) / (float)M_PI;   // RAD TO DEG
    }    
}

要約すると、私の目的は、CALayer(OpenGLではない)を使用して、プログラムで「弾丸の物理」BOX(サイコロ)を表すことです。そのために、CATransformLayerを6つの変換されたレイヤーのコンテナーとして3Dオブジェクトに使用しています。

-私が今得ている結果は良くありません、グラフィカルなサイコロは回転しますが、明らかに間違っています...だから私はここで完全に間違ったことをしています...

質問:弾丸物理学の世界でBOXの「向きまたは回転」を取得できるとすると、返されたクォータニオンをCATransform3DMakeRotationで使用できるもの(角度)に変換するにはどうすればよいですか。

よろしくお願いします、

ルイス

4

1 に答える 1

1

これはひどいアプローチです。あなたは行列から始めて、それを四元数に変え、それをオイラー角に変え、そしてそれらを行列に変えます。

の代わりにgetOrientation()、を呼び出しgetCenterOfMassTransform().getBasis()てを取得しbtMatrix3x3ます。これをの左上にパックCATransform3Dし、残りをゼロで埋めます(ただしm44、1である必要があります)。

于 2012-03-04T20:44:43.670 に答える