📄 dxutcamera.cpp
字号:
D3DXVECTOR3 vLocalUp = D3DXVECTOR3(0,1,0);
D3DXVECTOR3 vLocalAhead = D3DXVECTOR3(0,0,1);
D3DXVec3TransformCoord( &vWorldUp, &vLocalUp, &mCameraRot );
D3DXVec3TransformCoord( &vWorldAhead, &vLocalAhead, &mCameraRot );
// Transform the position delta by the camera's rotation
D3DXVECTOR3 vPosDeltaWorld;
if( !m_bEnableYAxisMovement )
{
// If restricting Y movement, do not include pitch
// when transforming position delta vector.
D3DXMatrixRotationYawPitchRoll( &mCameraRot, m_fCameraYawAngle, 0.0f, 0.0f );
}
D3DXVec3TransformCoord( &vPosDeltaWorld, &vPosDelta, &mCameraRot );
// Move the eye position
m_vEye += vPosDeltaWorld;
if( m_bClipToBoundary )
ConstrainToBoundary( &m_vEye );
// Update the lookAt position based on the eye position
m_vLookAt = m_vEye + vWorldAhead;
// Update the view matrix
D3DXMatrixLookAtLH( &m_mView, &m_vEye, &m_vLookAt, &vWorldUp );
D3DXMatrixInverse( &m_mCameraWorld, NULL, &m_mView );
}
//--------------------------------------------------------------------------------------
// Enable or disable each of the mouse buttons for rotation drag.
//--------------------------------------------------------------------------------------
void CFirstPersonCamera::SetRotateButtons( bool bLeft, bool bMiddle, bool bRight, bool bRotateWithoutButtonDown )
{
m_nActiveButtonMask = ( bLeft ? MOUSE_LEFT_BUTTON : 0 ) |
( bMiddle ? MOUSE_MIDDLE_BUTTON : 0 ) |
( bRight ? MOUSE_RIGHT_BUTTON : 0 );
m_bRotateWithoutButtonDown = bRotateWithoutButtonDown;
}
//--------------------------------------------------------------------------------------
// Constructor
//--------------------------------------------------------------------------------------
CModelViewerCamera::CModelViewerCamera()
{
D3DXMatrixIdentity( &m_mWorld );
D3DXMatrixIdentity( &m_mModelRot );
D3DXMatrixIdentity( &m_mModelLastRot );
D3DXMatrixIdentity( &m_mCameraRotLast );
m_vModelCenter = D3DXVECTOR3(0,0,0);
m_fRadius = 5.0f;
m_fDefaultRadius = 5.0f;
m_fMinRadius = 1.0f;
m_fMaxRadius = FLT_MAX;
m_bLimitPitch = false;
m_bEnablePositionMovement = false;
m_bAttachCameraToModel = false;
m_nRotateModelButtonMask = MOUSE_LEFT_BUTTON;
m_nZoomButtonMask = MOUSE_WHEEL;
m_nRotateCameraButtonMask = MOUSE_RIGHT_BUTTON;
m_bDragSinceLastUpdate = true;
}
//--------------------------------------------------------------------------------------
// Update the view matrix & the model's world matrix based
// on user input & elapsed time
//--------------------------------------------------------------------------------------
VOID CModelViewerCamera::FrameMove( FLOAT fElapsedTime )
{
if( IsKeyDown(m_aKeys[CAM_RESET]) )
Reset();
// If no dragged has happend since last time FrameMove is called,
// and no camera key is held down, then no need to handle again.
if( !m_bDragSinceLastUpdate && 0 == m_cKeysDown )
return;
m_bDragSinceLastUpdate = false;
//// If no mouse button is held down,
//// Get the mouse movement (if any) if the mouse button are down
//if( m_nCurrentButtonMask != 0 )
// UpdateMouseDelta( fElapsedTime );
GetInput( m_bEnablePositionMovement, m_nCurrentButtonMask != 0, true, false );
// Get amount of velocity based on the keyboard input and drag (if any)
UpdateVelocity( fElapsedTime );
// Simple euler method to calculate position delta
D3DXVECTOR3 vPosDelta = m_vVelocity * fElapsedTime;
// Change the radius from the camera to the model based on wheel scrolling
if( m_nMouseWheelDelta && m_nZoomButtonMask == MOUSE_WHEEL )
m_fRadius -= m_nMouseWheelDelta * m_fRadius * 0.1f / 120.0f;
m_fRadius = __min( m_fMaxRadius, m_fRadius );
m_fRadius = __max( m_fMinRadius, m_fRadius );
m_nMouseWheelDelta = 0;
// Get the inverse of the arcball's rotation matrix
D3DXMATRIX mCameraRot;
D3DXMatrixInverse( &mCameraRot, NULL, m_ViewArcBall.GetRotationMatrix() );
// Transform vectors based on camera's rotation matrix
D3DXVECTOR3 vWorldUp, vWorldAhead;
D3DXVECTOR3 vLocalUp = D3DXVECTOR3(0,1,0);
D3DXVECTOR3 vLocalAhead = D3DXVECTOR3(0,0,1);
D3DXVec3TransformCoord( &vWorldUp, &vLocalUp, &mCameraRot );
D3DXVec3TransformCoord( &vWorldAhead, &vLocalAhead, &mCameraRot );
// Transform the position delta by the camera's rotation
D3DXVECTOR3 vPosDeltaWorld;
D3DXVec3TransformCoord( &vPosDeltaWorld, &vPosDelta, &mCameraRot );
// Move the lookAt position
m_vLookAt += vPosDeltaWorld;
if( m_bClipToBoundary )
ConstrainToBoundary( &m_vLookAt );
// Update the eye point based on a radius away from the lookAt position
m_vEye = m_vLookAt - vWorldAhead * m_fRadius;
// Update the view matrix
D3DXMatrixLookAtLH( &m_mView, &m_vEye, &m_vLookAt, &vWorldUp );
D3DXMATRIX mInvView;
D3DXMatrixInverse( &mInvView, NULL, &m_mView );
mInvView._41 = mInvView._42 = mInvView._43 = 0;
D3DXMATRIX mModelLastRotInv;
D3DXMatrixInverse(&mModelLastRotInv, NULL, &m_mModelLastRot);
// Accumulate the delta of the arcball's rotation in view space.
// Note that per-frame delta rotations could be problematic over long periods of time.
D3DXMATRIX mModelRot;
mModelRot = *m_WorldArcBall.GetRotationMatrix();
m_mModelRot *= m_mView * mModelLastRotInv * mModelRot * mInvView;
if( m_ViewArcBall.IsBeingDragged() && m_bAttachCameraToModel && !IsKeyDown(m_aKeys[CAM_CONTROLDOWN]) )
{
// Attach camera to model by inverse of the model rotation
D3DXMATRIX mCameraLastRotInv;
D3DXMatrixInverse(&mCameraLastRotInv, NULL, &m_mCameraRotLast);
D3DXMATRIX mCameraRotDelta = mCameraLastRotInv * mCameraRot; // local to world matrix
m_mModelRot *= mCameraRotDelta;
}
m_mCameraRotLast = mCameraRot;
m_mModelLastRot = mModelRot;
// Since we're accumulating delta rotations, we need to orthonormalize
// the matrix to prevent eventual matrix skew
D3DXVECTOR3* pXBasis = (D3DXVECTOR3*) &m_mModelRot._11;
D3DXVECTOR3* pYBasis = (D3DXVECTOR3*) &m_mModelRot._21;
D3DXVECTOR3* pZBasis = (D3DXVECTOR3*) &m_mModelRot._31;
D3DXVec3Normalize( pXBasis, pXBasis );
D3DXVec3Cross( pYBasis, pZBasis, pXBasis );
D3DXVec3Normalize( pYBasis, pYBasis );
D3DXVec3Cross( pZBasis, pXBasis, pYBasis );
// Translate the rotation matrix to the same position as the lookAt position
m_mModelRot._41 = m_vLookAt.x;
m_mModelRot._42 = m_vLookAt.y;
m_mModelRot._43 = m_vLookAt.z;
// Translate world matrix so its at the center of the model
D3DXMATRIX mTrans;
D3DXMatrixTranslation( &mTrans, -m_vModelCenter.x, -m_vModelCenter.y, -m_vModelCenter.z );
m_mWorld = mTrans * m_mModelRot;
}
void CModelViewerCamera::SetDragRect( RECT &rc )
{
CBaseCamera::SetDragRect( rc );
m_WorldArcBall.SetOffset( rc.left, rc.top );
m_ViewArcBall.SetOffset( rc.left, rc.top );
SetWindow( rc.right - rc.left, rc.bottom - rc.top );
}
//--------------------------------------------------------------------------------------
// Reset the camera's position back to the default
//--------------------------------------------------------------------------------------
VOID CModelViewerCamera::Reset()
{
CBaseCamera::Reset();
D3DXMatrixIdentity( &m_mWorld );
D3DXMatrixIdentity( &m_mModelRot );
D3DXMatrixIdentity( &m_mModelLastRot );
D3DXMatrixIdentity( &m_mCameraRotLast );
m_fRadius = m_fDefaultRadius;
m_WorldArcBall.Reset();
m_ViewArcBall.Reset();
}
//--------------------------------------------------------------------------------------
// Override for setting the view parameters
//--------------------------------------------------------------------------------------
void CModelViewerCamera::SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt )
{
CBaseCamera::SetViewParams( pvEyePt, pvLookatPt );
// Propogate changes to the member arcball
D3DXQUATERNION quat;
D3DXMATRIXA16 mRotation;
D3DXVECTOR3 vUp(0,1,0);
D3DXMatrixLookAtLH( &mRotation, pvEyePt, pvLookatPt, &vUp );
D3DXQuaternionRotationMatrix( &quat, &mRotation );
m_ViewArcBall.SetQuatNow( quat );
// Set the radius according to the distance
D3DXVECTOR3 vEyeToPoint;
D3DXVec3Subtract( &vEyeToPoint, pvLookatPt, pvEyePt );
SetRadius( D3DXVec3Length( &vEyeToPoint ) );
// View information changed. FrameMove should be called.
m_bDragSinceLastUpdate = true;
}
//--------------------------------------------------------------------------------------
// Call this from your message proc so this class can handle window messages
//--------------------------------------------------------------------------------------
LRESULT CModelViewerCamera::HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
CBaseCamera::HandleMessages( hWnd, uMsg, wParam, lParam );
if( ( (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_LEFT_BUTTON) ||
( (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_MIDDLE_BUTTON) ||
( (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_RIGHT_BUTTON) )
{
int iMouseX = (short)LOWORD(lParam);
int iMouseY = (short)HIWORD(lParam);
m_WorldArcBall.OnBegin( iMouseX, iMouseY );
}
if( ( (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) && m_nRotateCameraButtonMask & MOUSE_LEFT_BUTTON) ||
( (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) && m_nRotateCameraButtonMask & MOUSE_MIDDLE_BUTTON) ||
( (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) && m_nRotateCameraButtonMask & MOUSE_RIGHT_BUTTON) )
{
int iMouseX = (short)LOWORD(lParam);
int iMouseY = (short)HIWORD(lParam);
m_ViewArcBall.OnBegin( iMouseX, iMouseY );
}
if( uMsg == WM_MOUSEMOVE )
{
int iMouseX = (short)LOWORD(lParam);
int iMouseY = (short)HIWORD(lParam);
m_WorldArcBall.OnMove( iMouseX, iMouseY );
m_ViewArcBall.OnMove( iMouseX, iMouseY );
}
if( (uMsg == WM_LBUTTONUP && m_nRotateModelButtonMask & MOUSE_LEFT_BUTTON) ||
(uMsg == WM_MBUTTONUP && m_nRotateModelButtonMask & MOUSE_MIDDLE_BUTTON) ||
(uMsg == WM_RBUTTONUP && m_nRotateModelButtonMask & MOUSE_RIGHT_BUTTON) )
{
m_WorldArcBall.OnEnd();
}
if( (uMsg == WM_LBUTTONUP && m_nRotateCameraButtonMask & MOUSE_LEFT_BUTTON) ||
(uMsg == WM_MBUTTONUP && m_nRotateCameraButtonMask & MOUSE_MIDDLE_BUTTON) ||
(uMsg == WM_RBUTTONUP && m_nRotateCameraButtonMask & MOUSE_RIGHT_BUTTON) )
{
m_ViewArcBall.OnEnd();
}
if( uMsg == WM_CAPTURECHANGED )
{
if( (HWND)lParam != hWnd )
{
if( (m_nRotateModelButtonMask & MOUSE_LEFT_BUTTON) ||
(m_nRotateModelButtonMask & MOUSE_MIDDLE_BUTTON) ||
(m_nRotateModelButtonMask & MOUSE_RIGHT_BUTTON) )
{
m_WorldArcBall.OnEnd();
}
if( (m_nRotateCameraButtonMask & MOUSE_LEFT_BUTTON) ||
(m_nRotateCameraButtonMask & MOUSE_MIDDLE_BUTTON) ||
(m_nRotateCameraButtonMask & MOUSE_RIGHT_BUTTON) )
{
m_ViewArcBall.OnEnd();
}
}
}
if( uMsg == WM_LBUTTONDOWN ||
uMsg == WM_LBUTTONDBLCLK ||
uMsg == WM_MBUTTONDOWN ||
uMsg == WM_MBUTTONDBLCLK ||
uMsg == WM_RBUTTONDOWN ||
uMsg == WM_RBUTTONDBLCLK ||
uMsg == WM_LBUTTONUP ||
uMsg == WM_MBUTTONUP ||
uMsg == WM_RBUTTONUP ||
uMsg == WM_MOUSEWHEEL ||
uMsg == WM_MOUSEMOVE )
{
m_bDragSinceLastUpdate = true;
}
return FALSE;
}
//--------------------------------------------------------------------------------------
// D3D9
IDirect3DDevice9* CDXUTDirectionWidget::s_pd3d9Device = NULL;
ID3DXEffect* CDXUTDirectionWidget::s_pD3D9Effect = NULL;
ID3DXMesh* CDXUTDirectionWidget::s_pD3D9Mesh = NULL;
// D3D10
ID3D10Device* CDXUTDirectionWidget::s_pd3d10Device = NULL;
ID3D10Effect* CDXUTDirectionWidget::s_pD3D10Effect = NULL;
ID3D10InputLayout* CDXUTDirectionWidget::s_pVertexLayout = NULL;
ID3D10EffectTechnique* CDXUTDirectionWidget::s_pRenderTech = NULL;
ID3D10EffectVectorVariable* CDXUTDirectionWidget::g_pMaterialDiffuseColor = NULL;
ID3D10EffectVectorVariable* CDXUTDirectionWidget::g_pLightDir = NULL;
ID3D10EffectMatrixVariable* CDXUTDirectionWidget::g_pmWorld = NULL;
ID3D10EffectMatrixVariable* CDXUTDirectionWidget::g_pmWorldViewProjection = NULL;
//--------------------------------------------------------------------------------------
CDXUTDirectionWidget::CDXUTDirectionWidget()
{
m_fRadius = 1.0f;
m_vDefaultDir = D3DXVECTOR3(0,1,0);
m_vCurrentDir = m_vDefaultDir;
m_nRotateMask = MOUSE_RIGHT_BUTTON;
D3DXMatrixIdentity( &m_mView );
D3DXMatrixIdentity( &m_mRot );
D3DXMatrixIdentity( &m_mRotSnapshot );
}
//--------------------------------------------------------------------------------------
HRESULT CDXUTDirectionWidget::StaticOnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice )
{
HRESULT hr;
s_pd3d9Device = pd3dDevice;
const char* g_strBuffer =
"float4 g_MaterialDiffuseColor; // Material's diffuse color\r\n"
"float3 g_LightDir; // Light's direction in world space\r\n"
"float4x4 g_mWorld; // World matrix for object\r\n"
"float4x4 g_mWorldViewProjection; // World * View * Projection matrix\r\n"
"\r\n"
"struct VS_OUTPUT\r\n"
"{\r\n"
" float4 Position : POSITION; // vertex position\r\n"
" float4 Diffuse : COLOR0; // vertex diffuse color\r\n"
"};\r\n"
"\r\n"
"VS_OUTPUT RenderWith1LightNoTextureVS( float4 vPos : POSITION,\r\n"
" float3 vNormal : NORMAL )\r\n"
"{\r\n"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -