📄 dxutmisc.cpp
字号:
//--------------------------------------------------------------------------------------
D3DXQUATERNION CD3DArcBall::QuatFromBallPoints(const D3DXVECTOR3 &vFrom, const D3DXVECTOR3 &vTo)
{
D3DXVECTOR3 vPart;
float fDot = D3DXVec3Dot(&vFrom, &vTo);
D3DXVec3Cross(&vPart, &vFrom, &vTo);
return D3DXQUATERNION(vPart.x, vPart.y, vPart.z, fDot);
}
//--------------------------------------------------------------------------------------
void CD3DArcBall::OnBegin( int nX, int nY )
{
// Only enter the drag state if the click falls
// inside the click rectangle.
if( nX >= m_Offset.x &&
nX < m_Offset.x + m_nWidth &&
nY >= m_Offset.y &&
nY < m_Offset.y + m_nHeight )
{
m_bDrag = true;
m_qDown = m_qNow;
m_vDownPt = ScreenToVector( (float)nX, (float)nY );
}
}
//--------------------------------------------------------------------------------------
void CD3DArcBall::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 CD3DArcBall::OnEnd()
{
m_bDrag = false;
}
//--------------------------------------------------------------------------------------
// Desc:
//--------------------------------------------------------------------------------------
LRESULT CD3DArcBall::HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
// 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 );
return TRUE;
case WM_LBUTTONUP:
ReleaseCapture();
OnEnd();
return TRUE;
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDOWN:
case WM_MBUTTONDBLCLK:
SetCapture( hWnd );
// Store off the position of the cursor when the button is pressed
m_ptLastMouse.x = iMouseX;
m_ptLastMouse.y = iMouseY;
return TRUE;
case WM_RBUTTONUP:
case WM_MBUTTONUP:
ReleaseCapture();
return TRUE;
case WM_MOUSEMOVE:
if( MK_LBUTTON&wParam )
{
OnMove( iMouseX, iMouseY );
}
else if( (MK_RBUTTON&wParam) || (MK_MBUTTON&wParam) )
{
// Normalize based on size of window and bounding sphere radius
FLOAT fDeltaX = ( m_ptLastMouse.x-iMouseX ) * m_fRadiusTranslation / m_nWidth;
FLOAT fDeltaY = ( m_ptLastMouse.y-iMouseY ) * m_fRadiusTranslation / m_nHeight;
if( wParam & MK_RBUTTON )
{
D3DXMatrixTranslation( &m_mTranslationDelta, -2*fDeltaX, 2*fDeltaY, 0.0f );
D3DXMatrixMultiply( &m_mTranslation, &m_mTranslation, &m_mTranslationDelta );
}
else // wParam & MK_MBUTTON
{
D3DXMatrixTranslation( &m_mTranslationDelta, 0.0f, 0.0f, 5*fDeltaY );
D3DXMatrixMultiply( &m_mTranslation, &m_mTranslation, &m_mTranslationDelta );
}
// Store mouse coordinate
m_ptLastMouse.x = iMouseX;
m_ptLastMouse.y = iMouseY;
}
return TRUE;
}
return FALSE;
}
//--------------------------------------------------------------------------------------
// Constructor
//--------------------------------------------------------------------------------------
CBaseCamera::CBaseCamera()
{
ZeroMemory( m_aKeys, sizeof(BYTE)*CAM_MAX_KEYS );
// Set attributes for the view matrix
D3DXVECTOR3 vEyePt = D3DXVECTOR3(0.0f,0.0f,0.0f);
D3DXVECTOR3 vLookatPt = D3DXVECTOR3(0.0f,0.0f,1.0f);
// Setup the view matrix
SetViewParams( &vEyePt, &vLookatPt );
// Setup the projection matrix
SetProjParams( D3DX_PI/4, 1.0f, 1.0f, 1000.0f );
GetCursorPos( &m_ptLastMousePosition );
m_bMouseLButtonDown = false;
m_bMouseMButtonDown = false;
m_bMouseRButtonDown = false;
m_nCurrentButtonMask = 0;
m_nMouseWheelDelta = 0;
m_fCameraYawAngle = 0.0f;
m_fCameraPitchAngle = 0.0f;
SetRect( &m_rcDrag, LONG_MIN, LONG_MIN, LONG_MAX, LONG_MAX );
m_vVelocity = D3DXVECTOR3(0,0,0);
m_bMovementDrag = false;
m_vVelocityDrag = D3DXVECTOR3(0,0,0);
m_fDragTimer = 0.0f;
m_fTotalDragTimeToZero = 0.25;
m_vRotVelocity = D3DXVECTOR2(0,0);
m_fRotationScaler = 0.01f;
m_fMoveScaler = 5.0f;
m_bInvertPitch = false;
m_bEnableYAxisMovement = true;
m_bEnablePositionMovement = true;
m_vMouseDelta = D3DXVECTOR2(0,0);
m_fFramesToSmoothMouseData = 2.0f;
m_bClipToBoundary = false;
m_vMinBoundary = D3DXVECTOR3(-1,-1,-1);
m_vMaxBoundary = D3DXVECTOR3(1,1,1);
m_bResetCursorAfterMove = false;
}
//--------------------------------------------------------------------------------------
// Client can call this to change the position and direction of camera
//--------------------------------------------------------------------------------------
VOID CBaseCamera::SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt )
{
if( NULL == pvEyePt || NULL == pvLookatPt )
return;
m_vDefaultEye = m_vEye = *pvEyePt;
m_vDefaultLookAt = m_vLookAt = *pvLookatPt;
// Calc the view matrix
D3DXVECTOR3 vUp(0,1,0);
D3DXMatrixLookAtLH( &m_mView, pvEyePt, pvLookatPt, &vUp );
D3DXMATRIX mInvView;
D3DXMatrixInverse( &mInvView, NULL, &m_mView );
// The axis basis vectors and camera position are stored inside the
// position matrix in the 4 rows of the camera's world matrix.
// To figure out the yaw/pitch of the camera, we just need the Z basis vector
D3DXVECTOR3* pZBasis = (D3DXVECTOR3*) &mInvView._31;
m_fCameraYawAngle = atan2f( pZBasis->x, pZBasis->z );
float fLen = sqrtf(pZBasis->z*pZBasis->z + pZBasis->x*pZBasis->x);
m_fCameraPitchAngle = -atan2f( pZBasis->y, fLen );
}
//--------------------------------------------------------------------------------------
// Calculates the projection matrix based on input params
//--------------------------------------------------------------------------------------
VOID CBaseCamera::SetProjParams( FLOAT fFOV, FLOAT fAspect, FLOAT fNearPlane,
FLOAT fFarPlane )
{
// Set attributes for the projection matrix
m_fFOV = fFOV;
m_fAspect = fAspect;
m_fNearPlane = fNearPlane;
m_fFarPlane = fFarPlane;
D3DXMatrixPerspectiveFovLH( &m_mProj, fFOV, fAspect, fNearPlane, fFarPlane );
}
//--------------------------------------------------------------------------------------
// Call this from your message proc so this class can handle window messages
//--------------------------------------------------------------------------------------
LRESULT CBaseCamera::HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
UNREFERENCED_PARAMETER( hWnd );
UNREFERENCED_PARAMETER( lParam );
switch( uMsg )
{
case WM_KEYDOWN:
{
// Map this key to a D3DUtil_CameraKeys enum and update the
// state of m_aKeys[] by adding the KEY_WAS_DOWN_MASK|KEY_IS_DOWN_MASK mask
// only if the key is not down
D3DUtil_CameraKeys mappedKey = MapKey( (UINT)wParam );
if( mappedKey != CAM_UNKNOWN )
{
if( FALSE == IsKeyDown(m_aKeys[mappedKey]) )
m_aKeys[ mappedKey ] = KEY_WAS_DOWN_MASK | KEY_IS_DOWN_MASK;
}
break;
}
case WM_KEYUP:
{
// Map this key to a D3DUtil_CameraKeys enum and update the
// state of m_aKeys[] by removing the KEY_IS_DOWN_MASK mask.
D3DUtil_CameraKeys mappedKey = MapKey( (UINT)wParam );
if( mappedKey != CAM_UNKNOWN )
m_aKeys[ mappedKey ] &= ~KEY_IS_DOWN_MASK;
break;
}
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_LBUTTONDOWN:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDBLCLK:
case WM_LBUTTONDBLCLK:
{
// Compute the drag rectangle in screen coord.
POINT ptCursor = { (short)LOWORD(lParam), (short)HIWORD(lParam) };
// Update member var state
if( ( uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) && PtInRect( &m_rcDrag, ptCursor ) )
{ m_bMouseLButtonDown = true; m_nCurrentButtonMask |= MOUSE_LEFT_BUTTON; }
if( ( uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) && PtInRect( &m_rcDrag, ptCursor ) )
{ m_bMouseMButtonDown = true; m_nCurrentButtonMask |= MOUSE_MIDDLE_BUTTON; }
if( ( uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) && PtInRect( &m_rcDrag, ptCursor ) )
{ m_bMouseRButtonDown = true; m_nCurrentButtonMask |= MOUSE_RIGHT_BUTTON; }
// Capture the mouse, so if the mouse button is
// released outside the window, we'll get the WM_LBUTTONUP message
SetCapture(hWnd);
GetCursorPos( &m_ptLastMousePosition );
return TRUE;
}
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_LBUTTONUP:
{
// Update member var state
if( uMsg == WM_LBUTTONUP ) { m_bMouseLButtonDown = false; m_nCurrentButtonMask &= ~MOUSE_LEFT_BUTTON; }
if( uMsg == WM_MBUTTONUP ) { m_bMouseMButtonDown = false; m_nCurrentButtonMask &= ~MOUSE_MIDDLE_BUTTON; }
if( uMsg == WM_RBUTTONUP ) { m_bMouseRButtonDown = false; m_nCurrentButtonMask &= ~MOUSE_RIGHT_BUTTON; }
// Release the capture if no mouse buttons down
if( !m_bMouseLButtonDown &&
!m_bMouseRButtonDown &&
!m_bMouseMButtonDown )
{
ReleaseCapture();
}
break;
}
case WM_MOUSEWHEEL:
// Update member var state
m_nMouseWheelDelta = (short)HIWORD(wParam) / 120;
break;
}
return FALSE;
}
//--------------------------------------------------------------------------------------
// Figure out the mouse delta based on mouse movement
//--------------------------------------------------------------------------------------
void CBaseCamera::UpdateMouseDelta( float fElapsedTime )
{
UNREFERENCED_PARAMETER( fElapsedTime );
POINT ptCurMouseDelta;
POINT ptCurMousePos;
// Get current position of mouse
GetCursorPos( &ptCurMousePos );
// Calc how far it's moved since last frame
ptCurMouseDelta.x = ptCurMousePos.x - m_ptLastMousePosition.x;
ptCurMouseDelta.y = ptCurMousePos.y - m_ptLastMousePosition.y;
// Record current position for next time
m_ptLastMousePosition = ptCurMousePos;
if( m_bResetCursorAfterMove )
{
// Set position of camera to center of desktop,
// so it always has room to move. This is very useful
// if the cursor is hidden. If this isn't done and cursor is hidden,
// then invisible cursor will hit the edge of the screen
// and the user can't tell what happened
POINT ptCenter;
RECT rcDesktop;
GetWindowRect( GetDesktopWindow(), &rcDesktop );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -