国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

D3D中四元數的表示

2019-11-08 03:16:51
字體:
來源:轉載
供稿:網友
1、定義。DIRECTX9文檔中定義,令q為一四元數,theta為繞軸axis旋轉的角度,則:q.x = sin(theta/2) * axis.xq.y = sin(theta/2) * axis.yq.z = sin(theta/2) * axis.zq.w = cos(theta/2)

可以簡單寫為:q = [sin(theta/2)axis, sin(theta/2)w] 或者 [x,y,z,w] 或者[v,w]

2、負四元數-q 。-q = [-q.x, -q.y, -q.z, -q.w]

3D幾何意義:軸變換了方向,角度也換了方向,剛好 -q = q。這個特性比較郁悶,在3D中任意方位,都有2種不同的四元數表示方法,竟然不是唯一的。

3、單位四元數q = [0,0,0,1].3D幾何意義:好像還看不出有什么幾何意義。補充:用處是為了表示旋轉0角度,一般用在變量初始化,和矩陣的單位初始話一個道理。D3DXQuaternionIdentity

D3DXQuaternionIsIdentity

4、四元數的長度或者模 ||q||。D3DXQuaternionLengthSq 長度的平方 = x*x + y*y + z*z + w*w;D3DXQuaternionLength 長度,上式的平方根。根據3D中四元數的定義,只有單位長度的四元數才有意義。盡管在DIRECTX中很多公式并不要求單位四元數,但是我們必須明白,只有單位四元數才有意義。補充:單位四元數的長度為1.

D3DXQuaternionNormalize,這個公式是求標準四元數,類似矢量的正則化。

5、共軛: [-x, -y, -z, w]。逆:共軛除于長度,記為q-1 。共軛: D3DXQuaternionConjugate逆:D3DXQuaternionInverse

3D幾何意義:相當于轉了一個相反的角。由于3D中只有單位長度的四元數才有意義,共軛和逆是一樣的。

6、四元數的點積。D3DXQuaternionDotq1.q2 = [v1,w1].[v2,w2]=v1.v2 + w1.w2 = x1x2+y1y2+z1z2+w1w2;

3D幾何意義:絕對值越大,2個方位越近似,夾角的余弦。補充:對于單位四元數,有-1 <= a.b <= +1,我們一般只關心其絕對值,和矢量點乘類似,絕對值越大,表示2個角度的角位移越小(即相似)。

7、四元數的叉積,一般我們說四元數的乘,指的就是這個叉積。D3DXQuaternionMultiply[v1,w1] X [v2,w2] = [w1v2 + w2v1 + v1 X v2, w1w2 - v1.v2];=[ w1x2 + x1w2 + z1y2 - y1z2,w1y2 + y1w2 + x1z2 - z1x2,w1z2 + z1w2 + y1x2 - x1y2,w1w2 - x1x2 - y1y2 - z1z2 ]特性:a、 結合律 (ab)c = a(bc). 交換律不滿足ab != ba b、 ||q1 q2|| = ||q1|| ||q2|| 這個說明:單位四元數相乘的結果還是單位四元數。c、 (ab)-1 = b-1a-1. 這個和矩陣的逆是一樣的。同理:

(Q1Q2...Q(n-1)Qn)-1 = Qn-1Q(n-1)-1...Q2-1Q1-1

8、四元數的差:一個方位到另一個方位的角位移。方位a旋轉到b的角位移為d,則ad = b. 經過推導:d = a-1b

這個差找不到相應的DIRECTX公式。

9、四元數的對數、指數運算。D3DXQuaternionLn,描述為:A unit quaternion, is defined by:Q == (cos(theta), sin(theta) * v) where |v| = 1The natural logarithm of Q is, ln(Q) = (0, theta * v)D3DXQuaternionExp,描述為:Given a pure quaternion defined by:Q = (0, theta * v);This method calculates the exponential result.

exp(Q) = (cos(theta), sin(theta) * v)

10、四元數的插值--slerpD3DXQuaternionSlerp四元數的精華就是可以線性平滑的進行插值。slerp__ Spherical Liear Interpolation.令矢量v0 v1之間的夾角為a, vt = k0v0 + k1v1;則:k0 = sin((1-t)a)/sin(a); k1 = sin(ta)/sin(a);

其中,二四元數之間的夾角余弦可以用點積來計算:x1x2+y1y2+z1z2+w1w2;

11、四個四元數之間的插值__Squad。很顯然是為了插值平滑平保證過渡點之間連續(DIRECTX 文檔說是保證過渡點間的切線連續,可以理解為矢量插值的二階連續)。用到如下2個公式:D3DXQuaternionSquadSetupD3DXQuaternionSquadDIRCTX 文檔中的例子:The following example shows how to use a set of quaternion keys (Q0, Q1, Q2, Q3) to compute the inner quadrangle points (A, B, C). This ensures that the tangents are continuous across adjacent segments.A B Q0 Q1 Q2 Q3The following code example demonstrates how you can interpolate between Q1 and Q2.// Rotation about the z-axisD3DXQUATERNION Q0 = D3DXQUATERNION(0, 0, 0.707f, -.707f);D3DXQUATERNION Q1 = D3DXQUATERNION(0, 0, 0.000f, 1.000f);D3DXQUATERNION Q2 = D3DXQUATERNION(0, 0, 0.707f, 0.707f);D3DXQUATERNION Q3 = D3DXQUATERNION(0, 0, 1.000f, 0.000f);D3DXQUATERNION A, B, C, Qt;FLOAT time = 0.5f;D3DXQuaternionSquadSetup(&A, &B, &C, &Q0, &Q1, &Q2, &Q3);D3DXQuaternionSquad(&Qt, &Q1, &A, &B, &C, time);注意: 1 C is +/- Q2 depending on the result of the function. (這點我還是不太明白哦?)2 Qt is the result of the function.The result is a rotation of 45 degrees around the z-axis for time = 0.5.DIRCTX9 的例子:SkinnedMesh Sample.12、四元數和矩陣的變換a. 矩陣變換到四元數,D3DXQuaternionRotationMatrixb. 更一般的,矩陣分解為比例,旋轉和位移三個分量:HRESULT WINAPI D3DXMatrixDecompose( D3DXVECTOR3 *pOutScale, D3DXQUATERNION *pOutRotation,D3DXVECTOR3 *pOutTranslation, CONST D3DXMATRIX *pM );c. 四元數變換到矩陣D3DXMATRIX* WINAPI D3DXMatrixRotationQuaternion( D3DXMATRIX *pOut, CONST D3DXQUATERNION *pQ);13、四元數和歐拉角的變換a. 歐拉角到四元數// Yaw around the Y axis, a pitch around the X axis,// and a roll around the Z axis.D3DXQUATERNION* WINAPI D3DXQuaternionRotationYawPitchRoll( D3DXQUATERNION *pOut, FLOAT Yaw, FLOAT Pitch, FLOAT Roll );b.繞軸旋轉// Rotation about arbitrary axis.D3DXQUATERNION* WINAPI D3DXQuaternionRotationAxis

( D3DXQUATERNION *pOut, CONST D3DXVECTOR3 *pV, FLOAT Angle );

插值的例子:

bool AnimationModelClass::Updatemd5Model(float deltaTime, int animation){       MD5Model.m_animations[animation].currAnimTime += deltaTime;         // Update the current animation time    if(MD5Model.m_animations[animation].currAnimTime > MD5Model.m_animations[animation].totalAnimTime)        MD5Model.m_animations[animation].currAnimTime = 0.0f;    // Which frame are we on    float currentFrame = MD5Model.m_animations[animation].currAnimTime * MD5Model.m_animations[animation].frameRate;        int frame0 = floorf( currentFrame );    int frame1 = frame0 + 1;    // Make sure we don't go over the number of frames      if(frame0 == MD5Model.m_animations[animation].numFrames-1)        frame1 = 0;    float interpolation = currentFrame - frame0;    // Get the remainder (in time) between frame0 and frame1 to use as interpolation factor    std::vector<Joint> interpolatedSkeleton;        // Create a frame skeleton to store the interpolated skeletons in    // Compute the interpolated skeleton    for( int i = 0; i < MD5Model.m_animations[animation].numJoints; i++)    {        Joint tempJoint;        Joint joint0 = MD5Model.m_animations[animation].frameSkeleton[frame0][i];       // Get the i'th joint of frame0's skeleton        Joint joint1 = MD5Model.m_animations[animation].frameSkeleton[frame1][i];       // Get the i'th joint of frame1's skeleton        tempJoint.parentID = joint0.parentID;                                           // Set the tempJoints parent id        // Turn the two quaternions into XMVECTORs for easy computations        D3DXQUATERNION joint0Orient = D3DXQUATERNION(joint0.orientation.x, joint0.orientation.y, joint0.orientation.z, joint0.orientation.w);        D3DXQUATERNION joint1Orient = D3DXQUATERNION(joint1.orientation.x, joint1.orientation.y, joint1.orientation.z, joint1.orientation.w);        // Interpolate positions        tempJoint.pos.x = joint0.pos.x + (interpolation * (joint1.pos.x - joint0.pos.x));        tempJoint.pos.y = joint0.pos.y + (interpolation * (joint1.pos.y - joint0.pos.y));        tempJoint.pos.z = joint0.pos.z + (interpolation * (joint1.pos.z - joint0.pos.z));        // Interpolate orientations using spherical interpolation (Slerp)        D3DXQUATERNION qtemp;        D3DXQuaternionSlerp(&qtemp, &joint0Orient, &joint1Orient, interpolation);        tempJoint.orientation.x = qtemp.x;        tempJoint.orientation.y = qtemp.y;        tempJoint.orientation.z = qtemp.z;        tempJoint.orientation.w = qtemp.w;        // Push the joint back into our interpolated skeleton        interpolatedSkeleton.push_back(tempJoint);          }    for ( int k = 0; k < MD5Model.numSubsets; k++)    {        for ( int i = 0; i < MD5Model.m_subsets[k].numVertices; ++i )        {            Vertex tempVert = MD5Model.m_subsets[k].m_vertices[i];            // Make sure the vertex's pos is cleared first            tempVert.x = 0;            tempVert.y = 0;            tempVert.z = 0;            // Clear vertices normal            tempVert.nx = 0;            tempVert.ny = 0;            tempVert.nz = 0;            // Sum up the joints and weights information to get vertex's position and normal            for ( int j = 0; j < tempVert.WeightCount; ++j )            {                Weight tempWeight = MD5Model.m_subsets[k].m_weights[tempVert.StartWeight + j];                Joint tempJoint = interpolatedSkeleton[tempWeight.jointID];                // Convert joint orientation and weight pos to vectors for easier computation                D3DXQUATERNION tempJointOrientation = D3DXQUATERNION(tempJoint.orientation.x, tempJoint.orientation.y, tempJoint.orientation.z, tempJoint.orientation.w);                D3DXQUATERNION tempWeightPos = D3DXQUATERNION(tempWeight.pos.x, tempWeight.pos.y, tempWeight.pos.z, 0.0f);                // We will need to use the conjugate of the joint orientation quaternion                D3DXQUATERNION tempJointOrientationConjugate;                D3DXQuaternionInverse(&tempJointOrientationConjugate, &tempJointOrientation);                // Calculate vertex position (in joint space, eg. rotate the point around (0,0,0)) for this weight using the joint orientation quaternion and its conjugate                // We can rotate a point using a quaternion with the equation "rotatedPoint = quaternion * point * quaternionConjugate"                D3DXVECTOR3 rotatedPoint;                D3DXQUATERNION QQtemp;                D3DXQuaternionMultiply(&qqtemp, &tempJointOrientation, &tempWeightPos);                D3DXQuaternionMultiply(&qqtemp, &qqtemp, &tempJointOrientationConjugate);                rotatedPoint.x = qqtemp.x;                rotatedPoint.y = qqtemp.y;                rotatedPoint.z = qqtemp.z;                // Now move the verices position from joint space (0,0,0) to the joints position in world space, taking the weights bias into account                tempVert.x += ( tempJoint.pos.x + rotatedPoint.x ) * tempWeight.bias;                tempVert.y += ( tempJoint.pos.y + rotatedPoint.y ) * tempWeight.bias;                tempVert.z += ( tempJoint.pos.z + rotatedPoint.z ) * tempWeight.bias;                // Compute the normals for this frames skeleton using the weight normals from before                // We can comput the normals the same way we compute the vertices position, only we don't have to translate them (just rotate)                D3DXQUATERNION tempWeightNormal = D3DXQUATERNION(tempWeight.normal.x, tempWeight.normal.y, tempWeight.normal.z, 0.0f);                D3DXQuaternionMultiply(&qqtemp, &tempJointOrientation, &tempWeightNormal);                D3DXQuaternionMultiply(&qqtemp, &qqtemp, &tempJointOrientationConjugate);                // Rotate the normal                rotatedPoint.x = qqtemp.x;                rotatedPoint.y = qqtemp.y;                rotatedPoint.z = qqtemp.z;                  // Add to vertices normal and ake weight bias into account                tempVert.nx -= rotatedPoint.x * tempWeight.bias;                tempVert.ny -= rotatedPoint.y * tempWeight.bias;                tempVert.nz -= rotatedPoint.z * tempWeight.bias;            }            // Store the vertices position in the position vector instead of straight into the vertex vector            MD5Model.m_subsets[k].m_positions[i].x = tempVert.x;                MD5Model.m_subsets[k].m_positions[i].y = tempVert.y;                MD5Model.m_subsets[k].m_positions[i].z = tempVert.z;                // Store the vertices normal            MD5Model.m_subsets[k].m_vertices[i].nx = tempVert.nx;               MD5Model.m_subsets[k].m_vertices[i].ny = tempVert.ny;               MD5Model.m_subsets[k].m_vertices[i].nz = tempVert.nz;               // Create the temp D3DXVECTOR3 for normalize            D3DXVECTOR3 dtemp = D3DXVECTOR3(0,0,0);            dtemp.x = MD5Model.m_subsets[k].m_vertices[i].nx;            dtemp.y = MD5Model.m_subsets[k].m_vertices[i].ny;            dtemp.z = MD5Model.m_subsets[k].m_vertices[i].nz;            D3DXVec3Normalize(&dtemp, &dtemp);            MD5Model.m_subsets[k].m_vertices[i].nx = dtemp.x;            MD5Model.m_subsets[k].m_vertices[i].ny = dtemp.y;            MD5Model.m_subsets[k].m_vertices[i].nz = dtemp.z;            // Put the positions into the vertices for this subset            MD5Model.m_subsets[k].m_vertices[i].x = MD5Model.m_subsets[k].m_positions[i].x;            MD5Model.m_subsets[k].m_vertices[i].y = MD5Model.m_subsets[k].m_positions[i].y;            MD5Model.m_subsets[k].m_vertices[i].z = MD5Model.m_subsets[k].m_positions[i].z;        }        // Update the subsets vertex buffer        // First lock the buffer        void* mappedVertBuff;        bool result;        result = MD5Model.m_subsets[k].vertBuff->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedVertBuff);        if(FAILED(result))        {            return false;        }        // Copy the data into the vertex buffer.        memcpy(mappedVertBuff, &MD5Model.m_subsets[k].m_vertices[0], (sizeof(Vertex) * MD5Model.m_subsets[k].numVertices));        MD5Model.m_subsets[k].vertBuff->Unmap();    }    return true;}相關的函數:

D3DXQUATERNION* WINAPI D3DXQuaternionBaryCentric//三個四元數的重心D3DXQUATERNION* D3DXQuaternionConjugate   //求共軛四元數FLOAT D3DXQuaternionDot     //四元數點乘D3DXQUATERNION* WINAPI D3DXQuaternionExp //四元數指數D3DXQUATERNION* WINAPI D3DXQuaternionInverse//共軛變換并規格化四元數D3DXQUATERNION* D3DXQuaternionIdentity   //單位四元數BOOL D3DXQuaternionIsIdentity    //判斷單位四元數FLOAT D3DXQuaternionLength    //返回四元數長度FLOAT D3DXQuaternionLengthSq    //返回四元數長度平方D3DXQUATERNION* WINAPI D3DXQuaternionLn   //計算自然對數D3DXQUATERNION* WINAPI D3DXQuaternionMultiply //兩個四元數相乘D3DXQUATERNION* WINAPI D3DXQuaternionNormalize //單位長度的四元數D3DXQUATERNION* WINAPI D3DXQuaternionRotationAxis//繞軸旋轉四元數D3DXQUATERNION* WINAPI D3DXQuaternionRotationMatrix//旋轉矩陣創建四元數D3DXQUATERNION* WINAPI D3DXQuaternionRotationYawPitchRoll//繞XYZ旋轉創建的四元數D3DXQUATERNION* WINAPI D3DXQuaternionSlerp //兩個四元數球面插值D3DXQUATERNION* WINAPI D3DXQuaternionSquad //球面四邊形插四元數void WINAPI D3DXQuaternionSquadSetup //創建球面四邊形插值的控制點void WINAPI D3DXQuaternionToAxisAngle//向量繞自身旋轉角度計算四元數

四元數旋轉物品:

首先我們需要定義一些變量來儲存所需信息D3DXQUATERNION g_qNow, g_qDown; //分別是 現在的旋轉用四元數 按下鼠標時的旋轉用四元數D3DXVECTOR3 g_vDownPt, g_vCurrentPt; //分別是 按下鼠標時的球面上的位置向量 當前的位置向量bool g_bDrag = false; //是否按下鼠標左鍵 用來判斷按鍵拖拽

然后初始化這些變量D3DXQuaternionIdentity(&g_qNow);D3DXQuaternionIdentity(&g_qDown);g_bDrag = false;好了,初始化工作做完了,然后具體講下算法。在鼠標按下處理過程

case WM_LBUTTONDOWN:   {    int iMouseX = ( short )LOWord( lParam );    int iMouseY = ( short )HIWORD( lParam );    //得到屏幕坐標    g_bDrag = true;    g_qDown = g_qNow;    g_vDownPt = ScreenToVector( ( float )iMouseX, ( float )iMouseY );   //得到投影窗口下的坐標   }在鼠標移動處理過程

case WM_MOUSEMOVE:   {    if( g_bDrag )    {     int iMouseX = ( short )LOWORD( lParam );     int iMouseY = ( short )HIWORD( lParam );  //得到屏幕坐標     g_vCurrentPt = ScreenToVector( ( float )iMouseX, ( float )iMouseY );//得到投影窗口下的坐標     g_qNow = g_qDown * QuatFromBallPoints( g_vDownPt, g_vCurrentPt );    }   }

 

//看看QuatFromBallPoints函數

D3DXQUATERNION QuatFromBallPoints( const D3DXVECTOR3& vFrom, const D3DXVECTOR3& vTo ){ D3DXVECTOR3 vPart;                

 float fDot = D3DXVec3Dot( &vFrom, &vTo ); //取得兩向量的點乘,因為兩個都是單位向量,所以fDot等于cos theta 

 D3DXVec3Cross( &vPart, &vFrom, &vTo );//叉乘,獲得的是垂直于兩個向量的一個向量,即旋轉軸。其模等于|a||b|sin theta等于sin theta

 return D3DXQUATERNION( vPart.x, vPart.y, vPart.z, fDot );//正好構成一個旋轉2*theta角度的四元數}

 首先說一下旋轉四元數,一個(x*sin theta, y*sin theta, z*sin theta, cos theta)的四元數被用來旋轉2*theta角度。在上面的代碼中通過兩個單位向量得到了一個旋轉四元數。從效果上來說就是鼠標在球體上做過theta角度,物體就旋轉2*theta角度。這是一個很方便的解決方法,不僅省卻了換算,也使得物體能夠在一次拖拽中旋轉360度。現在大部分事情都清楚了,接下來只要在繪制之前把世界矩陣按所得的旋轉四元數旋轉之后繪制物體就可以了。我們使用D3DXMatrixRotationQuaternion這個函數從四元數得到一個旋轉矩陣作為世界矩陣。D3DXMATRIXA16 matWorld;D3DXMatrixRotationQuaternion( &matWorld, &g_qNow );g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );至此完成,我們只需要在每一次繪制的時候按當前的旋轉四元數即g_qNow來設置世界矩陣即可。

//for (unsigned int i = 0; i < bones->size(); i++) {    //     unsigned long t0, t1;        D3DXQUATERNION q0, q1;        D3DXVECTOR3 p0, p1;        //========================================       //========================================    if (ite_keyFrames[i] != keyFrames[i].end()) {            //        t0 = (*ite_keyFrames[i]).frameNo;                //        boneRot[i] = q0 = (*ite_keyFrames[i]).rotation;                //        bonePos[i] = p0 = (*ite_keyFrames[i]).position;                //        if (++ite_keyFrames[i] != keyFrames[i].end()) {                    //            KeyFrame k = *ite_keyFrames[i];                        //            t1 = k.frameNo;                        //            q1 = k.rotation;                        //            p1 = k.position;            //========================================                       //(25 - 10) / 30 - 10 = 3 / 4 = 0.75 → 75%            //========================================            float s = (float)(time - t0) / (float)(t1 - t0);                        //========================================                       //========================================            D3DXQuaternionSlerp(&boneRot[i], &q0, &q1, k.bezie_r->GetY(s));                        bonePos[i].x = p0.x + (p1.x - p0.x)*k.bezie_x->GetY(s);                        bonePos[i].y = p0.y + (p1.y - p0.y)*k.bezie_y->GetY(s);                        bonePos[i].z = p0.z + (p1.z - p0.z)*k.bezie_z->GetY(s);                                    if (time != t1) --ite_keyFrames[i];        }    }    //========================================        //========================================    D3DXMATRIX rot, trans;        D3DXMatrixRotationQuaternion(&rot, &boneRot[i]);        D3DXMatrixTranslation(&trans, bonePos[i].x, bonePos[i].y, bonePos[i].z);    //========================================        //========================================    (*bones)[i].boneMatBL = rot*trans*(*bones)[i].initMatBL;}

參考:

http://blog.csdn.net/silangquan/article/details/50390570http://blog.csdn.net/ycl295644/article/details/50961201

1. C++標準模板庫從入門到精通 

http://edu.csdn.net/course/detail/3324

2.跟老菜鳥學C++

http://edu.csdn.net/course/detail/2901

3. 跟老菜鳥學python

http://edu.csdn.net/course/detail/2592

4. 在VC2015里學會使用tinyxml

http://edu.csdn.net/course/detail/2590

5. 在Windows下SVN的版本管理與實戰 

 http://edu.csdn.net/course/detail/2579

6.Visual Studio 2015開發C++程序的基本使用 

http://edu.csdn.net/course/detail/2570

7.在VC2015里使用PRotobuf協議

http://edu.csdn.net/course/detail/2582

8.在VC2015里學會使用MySQL數據庫

http://edu.csdn.net/course/detail/2672


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 库尔勒市| 建宁县| 新津县| 庆元县| 长岭县| 郎溪县| 贵德县| 闽侯县| 清新县| 出国| 景谷| 太仆寺旗| 南投市| 海晏县| 广汉市| 彭州市| 常山县| 三明市| 黄陵县| 常德市| 安徽省| 固镇县| 宁阳县| 聂荣县| 襄垣县| 静海县| 木兰县| 兖州市| 丘北县| 托里县| 山西省| 阳原县| 克拉玛依市| 会宁县| 萨迦县| 朝阳县| 英山县| 商洛市| 仁布县| 望谟县| 叙永县|