2013-04-01 2 views
1

나는 현재 (모델 뷰 카메라에 사용)를 아크 볼을 쓰고 있어요, 나는 MS DXUT 코드로 찾고, 그들은 기능의 이동에Quaternion multiplicatioin의 기하학적 의미는 무엇입니까?

#include "ArcBall.h" 

ArcBall::ArcBall(void) 
{ 
     Reset() ; 
     m_vDownPt = D3DXVECTOR3(0, 0, 0) ; 
     m_vCurrentPt = D3DXVECTOR3(0, 0, 0) ; 
     m_Offset.x = 0 ; 
     m_Offset.y = 0 ; 
} 

ArcBall::~ArcBall(void) 
{ 
} 

void ArcBall::Reset() 
{ 
     D3DXQuaternionIdentity(&m_qDown); 
     D3DXQuaternionIdentity(&m_qNow); 
     D3DXMatrixIdentity(&m_mRotation); 
     m_bDrag = FALSE; 
     m_fRadius = 1.0f; 

     RECT rc ; 
     GetClientRect(GetForegroundWindow(), &rc) ; 
     SetWindow(rc.right, rc.bottom) ; 
} 

void ArcBall::OnBegin(int nX, int nY) 
{ 
     // enter drag state only if user click the window's client area 
     if(nX >= m_Offset.x && 
       nX <= m_Offset.x + m_nWidth && 
       nY >= m_Offset.y && 
       nY < m_Offset.y + m_nHeight) 
     { 
       m_bDrag = true ; // begin drag state 
       m_qDown = m_qNow ; 
       m_vDownPt = ScreenToVector((float)nX, (float)nY) ; 
     } 
} 

void ArcBall::OnMove(int nX, int nY) 
{ 
     if(m_bDrag) 
     { 
       m_vCurrentPt = ScreenToVector((float)nX, (float)nY) ; 
       m_qNow = m_qDown * QuatFromBallPoints(m_vDownPt, m_vCurrentPt) ; 
     } 
} 

void ArcBall::OnEnd() 
{ 
     m_bDrag = false ; 
} 

void ArcBall::SetOffset(INT nX, INT nY) 
{ 
     m_Offset.x = nX ; 
     m_Offset.y = nY ; 
} 

void ArcBall::SetWindow(int nWidth, int nHeight, float fRadius) 
{ 
     m_nWidth = nWidth; 
     m_nHeight = nHeight; 
     m_fRadius = fRadius; 
     m_vCenter = D3DXVECTOR2(m_nWidth/2.0f, m_nHeight/2.0f); 
} 

const D3DXMATRIX* ArcBall::GetRotationMatrix() 
{ 
     return D3DXMatrixRotationQuaternion(&m_mRotation, &m_qNow) ; 
} 

D3DXQUATERNION ArcBall::QuatFromBallPoints(const D3DXVECTOR3 &vFrom, const D3DXVECTOR3 &vTo) 
{ 
     D3DXVECTOR3 vPart; 
     float fDot = D3DXVec3Dot(&vFrom, &vTo);  // rotation angle 
     D3DXVec3Cross(&vPart, &vFrom, &vTo);   // rotation axis 

     return D3DXQUATERNION(vPart.x, vPart.y, vPart.z, fDot); 
} 

D3DXVECTOR3 ArcBall::ScreenToVector(float fScreenPtX, float fScreenPtY) 
{ 
     // Scale to screen 
     // xֵΪ¸º£¬ÊÇÒòΪDirectXʹÓÃ×óÊÖϵ 
     FLOAT x = -(fScreenPtX - m_Offset.x - m_nWidth/2)/(m_fRadius * m_nWidth/2); 
     FLOAT y = (fScreenPtY - m_Offset.y - m_nHeight/2)/(m_fRadius * m_nHeight/2); 

     FLOAT z = 0.0f; 
     FLOAT mag = x * x + y * y; 

     if(mag > 1.0f) 
     { 
       FLOAT scale = 1.0f/sqrtf(mag); 
       x *= scale; 
       y *= scale; 
     } 
     else 
       z = sqrtf(1.0f - mag); 

     // Return vector 
     return D3DXVECTOR3(x, y, z); 
} 

아래로 아크 볼 구현을 가지고, 우리는 두 가지의 곱셈을 볼 수 있습니다 쿼터니언

m_qNow = m_qDown * QuatFromBallPoints(m_vDownPt, m_vCurrentPt) ; 

함수 QuatFromBallPoints는 두 점에서 쿼터니언 기초를 계산합니다. 나는 제품의 의미를 알고 싶습니까?

코드 설명 : arcball은 사용자가 마우스를 드래그 할 때 작동합니다. 마우스 버튼이 눌려 졌을 때 (왼쪽 버튼이라고 가정) OnBegin 함수가 호출되었습니다. 마우스 버튼을 누르면 OnEnd 함수가 호출되었으며, 사용자가 마우스를 끌 때 OnMove 함수가 호출되었습니다.

답변

2

곱셈은 회전 구성을 의미합니다. QuatFromBallPointsm_vDownPtm_vCurrentPt에 매핑하는 회전을 반환합니다. 이 새로운 회전은 arcball의 현재 회전 (드래그가 시작될 때의 회전)과 결합되어야합니다.

+0

[D3DXQuaternionMultiply] (http://msdn.microsoft.com/en-us/library/windows/desktop/bb205413(v=vs.85)asp.aspx) [XMQuaternionMultiply] (http://msdn.microsoft .com/en-us/library/windows/desktop/microsoft.directx_sdk.quaternion.xmquaternionmultiply (v = vs.85) .aspx) – zdd