游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2737|回复: 4

怎样用四元素实现模型旋转?

[复制链接]

48

主题

142

帖子

142

积分

注册会员

Rank: 2

积分
142
发表于 2006-9-25 15:05:00 | 显示全部楼层 |阅读模式
是不是QUATERNION*QUATERNION呀?
但模型怎么与QUATERNION挂上钩呀?
(可以详细点吗?谢谢!)

30

主题

90

帖子

94

积分

注册会员

Rank: 2

积分
94
发表于 2006-9-25 16:15:00 | 显示全部楼层

Re:怎样用四元素实现模型旋转?

这个函数可以把四元数转换为旋转矩阵
D3DXMATRIX * D3DXMatrixRotationQuaternion(
  D3DXMATRIX * pOut,
  CONST D3DXQUATERNION * pQ
);
四元数用于在两个旋转之间平滑的插值,所以应该是用D3DXQuaternionSlerp函数对两个四元数做插值,而不是求两个四元数的点积。

48

主题

142

帖子

142

积分

注册会员

Rank: 2

积分
142
 楼主| 发表于 2006-9-25 16:39:00 | 显示全部楼层

Re:怎样用四元素实现模型旋转?

一起读一读Samples的例子好吗?
EffectParam.cpp:
class CMeshArcBall : public CD3DArcBall
{
public:
    void OnBegin( int nX, int nY, D3DXMATRIXA16 *pmInvViewRotate )//(主要功能是取得与鼠标对应的三维向量)
    {
        m_bDrag = true;//(bool m_bDrag;  // Whether user is dragging arc ball)
        m_qDown = m_qNow;//(D3DXQUATERNION m_qDown; // Quaternion before button down,m_qNow;// Composite quaternion for current drag;单位四元素(0, 0, 0, 1))
        m_vDownPt = ScreenToVector( (float)nX, (float)nY );//( D3DXVECTOR3 m_vDownPt;// starting point of rotation arc,return D3DXVECTOR3( x, y, z );)
        D3DXVECTOR4 v;
        D3DXVec3Transform( &v, &m_vDownPt, pmInvViewRotate );//(用矩阵把向量(x, y, z, 1)进行变换)
        m_vDownPt = (D3DXVECTOR3)v;//(真是奇怪,好不容易变为四维的,又要变回,甚至物归原主)
    }
    void OnMove( int nX, int nY, D3DXMATRIXA16 *pmInvViewRotate )//(四元素相乘结果如何)
    {
        if (m_bDrag)
        {
            m_vCurrentPt = ScreenToVector( (float)nX, (float)nY );//(取向量)
            D3DXVECTOR4 v;
            D3DXVec3Transform( &v, &m_vCurrentPt, pmInvViewRotate );
            m_vCurrentPt = (D3DXVECTOR3)v;//(转换向量)
            m_qNow = m_qDown * QuatFromBallPoints( m_vDownPt, m_vCurrentPt );//(向量经过点乘、叉乘获得四元素,四元素相乘得四元素)
        }
    }
    LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, D3DXMATRIXA16 *pmInvViewRotate )
    {
        // Current mouse position
        int iMouseX = (short)LOWORD(lParam);
        int iMouseY = (short)HIWORD(lParam);

        switch( uMsg )
        {
            case WM_LBUTTONDOWN:
            case WM_LBUTTONDBLCLK:
                SetCapture( hWnd );
                OnBegin( iMouseX, iMouseY, pmInvViewRotate );
                return TRUE;

            case WM_LBUTTONUP:
                ReleaseCapture();
                OnEnd();
                return TRUE;

            case WM_CAPTURECHANGED:
                if( (HWND)lParam != hWnd )
                {
                    ReleaseCapture();
                    OnEnd();
                }
                return TRUE;

            case WM_MOUSEMOVE:
                if( MK_LBUTTON&wParam )
                {
                    OnMove( iMouseX, iMouseY, pmInvViewRotate );
                }
                return TRUE;
        }

        return FALSE;
    }
};
很难明白其中的奥妙.

30

主题

90

帖子

94

积分

注册会员

Rank: 2

积分
94
发表于 2006-9-25 20:45:00 | 显示全部楼层

Re:怎样用四元素实现模型旋转?

这是用来按住鼠标拖转场景的。看HandleMessages函数,当鼠标左键按下或双击的时候,OnBegin函数记录下了鼠标按下的位置(屏幕空间转到世界空间),然后移动鼠标(按住左键),每次移动鼠标都会发送WM_MOUSEMOVE消息给HandleMessages函数,该函数就调用OnMove函数,OnMove函数记录下当前鼠标的位置(屏幕空间转到世界空间)。这就有了两个位置:鼠标左键按下时的位置m_vDownPt和当前位置m_vCurrentPt,QuatFromBallPoints函数计算出从m_vDownPt转到(绕ArcBall的球心)m_vCurrentPt的对应四元数。四元数m_qDown在这个时候保存的还是上一次的旋转量,所以它乘上新的旋转四元数,就是当前总共旋转四元数,这个四元数保存到m_qNow中,而m_qNow的值会在下一次OnBegin的时候存到m_qDown里。
pmInvViewRotate不知道是个什么矩阵,难道是ArcBall的object view matrix的逆矩阵?我猜它是用来把位置转到ArcBall的局部空间的,所以上面说的位置其实是在ArcBall的局部空间中。

48

主题

142

帖子

142

积分

注册会员

Rank: 2

积分
142
 楼主| 发表于 2006-9-28 08:40:00 | 显示全部楼层

Re:怎样用四元素实现模型旋转?

LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext )
{
    // Always allow dialog resource manager calls to handle global messages
    // so GUI state is updated correctly
    *pbNoFurtherProcessing = g_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;

    if( g_SettingsDlg.IsActive() )
    {
        g_SettingsDlg.MsgProc( hWnd, uMsg, wParam, lParam );
        return 0;
    }

    // Give the dialogs a chance to handle the message first
    *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;
    *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;

    // Pass all remaining windows messages to camera so it can respond to user input
    g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
    D3DXMATRIXA16 mViewRotate = *g_Camera.GetViewMatrix();
    mViewRotate._41 = mViewRotate._42 = mViewRotate._43 = 0.0f;
    D3DXMatrixInverse( &mViewRotate, NULL, &mViewRotate );
    if( g_ArcBall.GetSize() > 0 )
        g_ArcBall[g_nActiveMesh].HandleMessages( hWnd, uMsg, wParam, lParam, &mViewRotate );//&mViewRotate 将传递给pmInvViewRotate,看来是视图矩阵.在此,模型就与四元素联系起了?

    return 0;
}
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-25 12:43

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表