1

openGL 回転行列からデータを取得する必要があります。同等のオイラー角 (すでに実行済み)、同等の四元数 (実行済みですが、インターネットからコピーしただけ)、および同等の軸角度を取得する必要があります。

回転行列が、特定のベクトルを中心とした特定の角度の単一の回転として表現できるかどうかはわかりません。これらは同等ですか?そうである場合、どうすれば一方を他方から取得できますか?

また、クォータニオンの意味と回転行列の内部をよりよく理解したいと思います。これについて学ぶにはどこに行けばよいですか?

4

2 に答える 2

1

はい、回転行列/単位四元数は、単一の軸を中心とした回転に相当します。この軸nと角度を呼び出すと、thetaこの回転のクォータニオンは次のようになります。

[n * sin(theta / 2) cos(theta / 2)]

これを再構築するには、四元数acosの要素を使用してを取得します。を分割した後、軸を再構築するためにコンポーネントを使用できます。wtheta / 2thetaxyzsin(theta / 2)

于 2012-04-16T10:54:40.993 に答える
0

これは、3x3 マトリックスを軸、角度に変換する関数です (四分法を使用するため、おそらくそのステップをバイパスするより効率的な方法があります)。

void axis_angle_from_mat3(float r_axis[3], float *r_angle, float mat[3][3])
{
    float q[4];

    /* -------------------------------------------------------------------- */
    /* matrix to quaternion */
    double tr, s;
    float tmat[3][3];

    /* work on a copy */
    memcpy(tmat, mat, sizeof(tmat));

    /* normalize the matrix */
    int i;
    for (i = 0; i < 3; i++) {
        float d = (tmat[i][0] * tmat[i][0] + tmat[i][1] * tmat[i][1] + tmat[i][2] * tmat[i][2]);

        if (d > 1.0e-35f) {
            d = sqrtf(d);
            tmat[i][0] /= d;
            tmat[i][1] /= d;
            tmat[i][2] /= d;
        }
        else {
            tmat[i][0] = 0.0f;
            tmat[i][1] = 0.0f;
            tmat[i][2] = 0.0f;
            d = 0.0f;
        }
    }


    tr = 0.25 * (double)(1.0f + tmat[0][0] + tmat[1][1] + tmat[2][2]);

    if (tr > (double)1e-4f) {
        s = sqrt(tr);
        q[0] = (float)s;
        s = 1.0 / (4.0 * s);
        q[1] = (float)((double)(tmat[1][2] - tmat[2][1]) * s);
        q[2] = (float)((double)(tmat[2][0] - tmat[0][2]) * s);
        q[3] = (float)((double)(tmat[0][1] - tmat[1][0]) * s);
    }
    else {
        if (tmat[0][0] > tmat[1][1] && tmat[0][0] > tmat[2][2]) {
            s = 2.0f * sqrtf(1.0f + tmat[0][0] - tmat[1][1] - tmat[2][2]);
            q[1] = (float)(0.25 * s);

            s = 1.0 / s;
            q[0] = (float)((double)(tmat[1][2] - tmat[2][1]) * s);
            q[2] = (float)((double)(tmat[1][0] + tmat[0][1]) * s);
            q[3] = (float)((double)(tmat[2][0] + tmat[0][2]) * s);
        }
        else if (tmat[1][1] > tmat[2][2]) {
            s = 2.0f * sqrtf(1.0f + tmat[1][1] - tmat[0][0] - tmat[2][2]);
            q[2] = (float)(0.25 * s);

            s = 1.0 / s;
            q[0] = (float)((double)(tmat[2][0] - tmat[0][2]) * s);
            q[1] = (float)((double)(tmat[1][0] + tmat[0][1]) * s);
            q[3] = (float)((double)(tmat[2][1] + tmat[1][2]) * s);
        }
        else {
            s = 2.0f * sqrtf(1.0f + tmat[2][2] - tmat[0][0] - tmat[1][1]);
            q[3] = (float)(0.25 * s);

            s = 1.0 / s;
            q[0] = (float)((double)(tmat[0][1] - tmat[1][0]) * s);
            q[1] = (float)((double)(tmat[2][0] + tmat[0][2]) * s);
            q[2] = (float)((double)(tmat[2][1] + tmat[1][2]) * s);
        }
    }


    /* normalize the quat */
    float len;
    len = sqrtf(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
    if (len != 0.0f) {
        q[0] /= len;
        q[1] /= len;
        q[2] /= len;
        q[3] /= len;
    }
    else {
        q[1] = 1.0f;
        q[0] = q[2] = q[3] = 0.0f;
    }


    /* -------------------------------------------------------------------- */
    /* quaternion to axis angle */

    float ha, si;

    ha = acosf(q[0]);
    si = sinf(ha);

    *r_angle = ha * 2;

    if (fabsf(si) < FLT_EPSILON)
        si = 1.0f;

    r_axis[0] = q[1] / si;
    r_axis[1] = q[2] / si;
    r_axis[2] = q[3] / si;
}
于 2014-04-19T07:32:58.290 に答える