日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

四元數(shù)和旋轉(zhuǎn)矩陣互相轉(zhuǎn)換

 賢人好客 2010-12-29
四元數(shù)的用途和好處我就不多說了。
之前在網(wǎng)上找旋轉(zhuǎn)矩陣和四元數(shù)相互轉(zhuǎn)換的代碼,找了幾個都不大對勁,正反算算不過來,最后還是從osg源碼里貼出來的這個,應(yīng)該沒什么問題。
這里給一個鏈接,Matrix and Quaternion FAQ http://www./documents/matrfaq.html

以下是源文件:

#include<iostream>
#include<cmath>
using namespace std;

typedef double ValType;

struct Quat;
struct Matrix;

struct Quat {
ValType _v[4];//x, y, z, w

/// Length of the quaternion = sqrt( vec . vec )
ValType length() const
{
    return sqrt( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] + _v[3]*_v[3]);
}

/// Length of the quaternion = vec . vec
ValType length2() const
{
    return _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] + _v[3]*_v[3];
}
};

struct Matrix {
ValType _mat[3][3];
};

#define QX q._v[0]
#define QY q._v[1]
#define QZ q._v[2]
#define QW q._v[3]

void Quat2Matrix(const Quat& q, Matrix& m)
{
    double length2 = q.length2();
    if (fabs(length2) <= std::numeric_limits<double>::min())
    {
        m._mat[0][0] = 0.0; m._mat[1][0] = 0.0; m._mat[2][0] = 0.0;
        m._mat[0][1] = 0.0; m._mat[1][1] = 0.0; m._mat[2][1] = 0.0;
        m._mat[0][2] = 0.0; m._mat[1][2] = 0.0; m._mat[2][2] = 0.0;
    }
    else
    {
        double rlength2;
        // normalize quat if required.
        // We can avoid the expensive sqrt in this case since all 'coefficients' below are products of two q components.
        // That is a square of a square root, so it is possible to avoid that
        if (length2 != 1.0)
        {
            rlength2 = 2.0/length2;
        }
        else
        {
            rlength2 = 2.0;
        }
       
        // Source: Gamasutra, Rotating Objects Using Quaternions
        //
        //http://www./features/19980703/quaternions_01.htm
       
        double wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
       
        // calculate coefficients
        x2 = rlength2*QX;
        y2 = rlength2*QY;
        z2 = rlength2*QZ;
       
        xx = QX * x2;
        xy = QX * y2;
        xz = QX * z2;
       
        yy = QY * y2;
        yz = QY * z2;
        zz = QZ * z2;
       
        wx = QW * x2;
        wy = QW * y2;
        wz = QW * z2;
       
        // Note. Gamasutra gets the matrix assignments inverted, resulting
        // in left-handed rotations, which is contrary to OpenGL and OSG's
        // methodology. The matrix assignment has been altered in the next
        // few lines of code to do the right thing.
        // Don Burns - Oct 13, 2001
        m._mat[0][0] = 1.0 - (yy + zz);
        m._mat[1][0] = xy - wz;
        m._mat[2][0] = xz + wy;
       
       
        m._mat[0][1] = xy + wz;
        m._mat[1][1] = 1.0 - (xx + zz);
        m._mat[2][1] = yz - wx;
       
        m._mat[0][2] = xz - wy;
        m._mat[1][2] = yz + wx;
        m._mat[2][2] = 1.0 - (xx + yy);
    }
}

void Matrix2Quat(const Matrix& m, Quat& q)
{
    ValType s;
    ValType tq[4];
    int    i, j;

    // Use tq to store the largest trace
    tq[0] = 1 + m._mat[0][0]+m._mat[1][1]+m._mat[2][2];
    tq[1] = 1 + m._mat[0][0]-m._mat[1][1]-m._mat[2][2];
    tq[2] = 1 - m._mat[0][0]+m._mat[1][1]-m._mat[2][2];
    tq[3] = 1 - m._mat[0][0]-m._mat[1][1]+m._mat[2][2];

    // Find the maximum (could also use stacked if's later)
    j = 0;
    for(i=1;i<4;i++) j = (tq[i]>tq[j])? i : j;

    // check the diagonal
    if (j==0)
    {
        /* perform instant calculation */
        QW = tq[0];
        QX = m._mat[1][2]-m._mat[2][1];
        QY = m._mat[2][0]-m._mat[0][2];
        QZ = m._mat[0][1]-m._mat[1][0];
    }
    else if (j==1)
    {
        QW = m._mat[1][2]-m._mat[2][1];
        QX = tq[1];
        QY = m._mat[0][1]+m._mat[1][0];
        QZ = m._mat[2][0]+m._mat[0][2];
    }
    else if (j==2)
    {
        QW = m._mat[2][0]-m._mat[0][2];
        QX = m._mat[0][1]+m._mat[1][0];
        QY = tq[2];
        QZ = m._mat[1][2]+m._mat[2][1];
    }
    else /* if (j==3) */
    {
        QW = m._mat[0][1]-m._mat[1][0];
        QX = m._mat[2][0]+m._mat[0][2];
        QY = m._mat[1][2]+m._mat[2][1];
        QZ = tq[3];
    }

    s = sqrt(0.25/tq[j]);
    QW *= s;
    QX *= s;
    QY *= s;
    QZ *= s;
}

void printMatrix(const Matrix& r, string name)
{
cout<<"RotMat "<<name<<" = "<<endl;
cout<<"\t"<<r._mat[0][0]<<" "<<r._mat[0][1]<<" "<<r._mat[0][2]<<endl;
cout<<"\t"<<r._mat[1][0]<<" "<<r._mat[1][1]<<" "<<r._mat[1][2]<<endl;
cout<<"\t"<<r._mat[2][0]<<" "<<r._mat[2][1]<<" "<<r._mat[2][2]<<endl;
cout<<endl;
}

void printQuat(const Quat& q, string name)
{
cout<<"Quat "<<name<<" = "<<endl;
cout<<"\t"<<q._v[0]<<" "<<q._v[1]<<" "<<q._v[2]<<" "<<q._v[3]<<endl;
cout<<endl;
}

int main()
{
ValType phi, omiga, kappa;

phi = 1.32148229302237 ; omiga = 0.626224465189316 ; kappa = -1.4092143985971;

    ValType a1,a2,a3,b1,b2,b3,c1,c2,c3;

    a1 = cos(phi)*cos(kappa) - sin(phi)*sin(omiga)*sin(kappa);
    a2 = -cos(phi)*sin(kappa) - sin(phi)*sin(omiga)*cos(kappa);
    a3 = -sin(phi)*cos(omiga);

    b1 = cos(omiga)*sin(kappa);
    b2 = cos(omiga)*cos(kappa);
    b3 = -sin(omiga);

    c1 = sin(phi)*cos(kappa) + cos(phi)*sin(omiga)*sin(kappa);
    c2 = -sin(phi)*sin(kappa) + cos(phi)*sin(omiga)*cos(kappa);
    c3 = cos(phi)*cos(omiga);
   
    Matrix r;
    r._mat[0][0] = a1;
r._mat[0][1] = a2;
r._mat[0][2] = a3;

r._mat[1][0] = b1;
r._mat[1][1] = b2;
r._mat[1][2] = b3;

r._mat[2][0] = c1;
r._mat[2][1] = c2;
r._mat[2][2] = c3;

printMatrix(r, "r");

     //////////////////////////////////////////////////////////

Quat q;
Matrix2Quat(r, q);

printQuat(q, "q");

Matrix _r;
Quat2Matrix(q, _r);

printMatrix(_r, "_r");
   
system("pause");
return 0;
}

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多