aboutsummaryrefslogtreecommitdiff
path: root/samples/DX_APIUsage/DXUT/Optional/DXUTcamera.cpp
diff options
context:
space:
mode:
authorDave Clark <[email protected]>2018-02-28 17:22:22 -0500
committerDave Clark <[email protected]>2018-02-28 17:22:22 -0500
commit25528fd230f5f4298c35123a833cdb112675808e (patch)
treef5aca3f5ee5a7734df41e7b974a04c37ddff528e /samples/DX_APIUsage/DXUT/Optional/DXUTcamera.cpp
parentPush GfeSDK #173 (diff)
downloadgfesdk-25528fd230f5f4298c35123a833cdb112675808e.tar.xz
gfesdk-25528fd230f5f4298c35123a833cdb112675808e.zip
Push SDK # 1.1.186
Documentation updates.
Diffstat (limited to 'samples/DX_APIUsage/DXUT/Optional/DXUTcamera.cpp')
-rw-r--r--samples/DX_APIUsage/DXUT/Optional/DXUTcamera.cpp1532
1 files changed, 1532 insertions, 0 deletions
diff --git a/samples/DX_APIUsage/DXUT/Optional/DXUTcamera.cpp b/samples/DX_APIUsage/DXUT/Optional/DXUTcamera.cpp
new file mode 100644
index 0000000..42e8ea4
--- /dev/null
+++ b/samples/DX_APIUsage/DXUT/Optional/DXUTcamera.cpp
@@ -0,0 +1,1532 @@
+//--------------------------------------------------------------------------------------
+// File: DXUTcamera.cpp
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//--------------------------------------------------------------------------------------
+#include "DXUT.h"
+#include "DXUTcamera.h"
+#include "DXUTres.h"
+#undef min // use __min instead
+#undef max // use __max instead
+
+//--------------------------------------------------------------------------------------
+CD3DArcBall::CD3DArcBall()
+{
+ Reset();
+ m_vDownPt = D3DXVECTOR3( 0, 0, 0 );
+ m_vCurrentPt = D3DXVECTOR3( 0, 0, 0 );
+ m_Offset.x = m_Offset.y = 0;
+
+ RECT rc;
+ GetClientRect( GetForegroundWindow(), &rc );
+ SetWindow( rc.right, rc.bottom );
+}
+
+
+
+
+
+//--------------------------------------------------------------------------------------
+void CD3DArcBall::Reset()
+{
+ D3DXQuaternionIdentity( &m_qDown );
+ D3DXQuaternionIdentity( &m_qNow );
+ D3DXMatrixIdentity( &m_mRotation );
+ D3DXMatrixIdentity( &m_mTranslation );
+ D3DXMatrixIdentity( &m_mTranslationDelta );
+ m_bDrag = FALSE;
+ m_fRadiusTranslation = 1.0f;
+ m_fRadius = 1.0f;
+}
+
+
+
+
+//--------------------------------------------------------------------------------------
+D3DXVECTOR3 CD3DArcBall::ScreenToVector( float fScreenPtX, float fScreenPtY )
+{
+ // Scale to screen
+ 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 );
+}
+
+
+
+
+//--------------------------------------------------------------------------------------
+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_CAPTURECHANGED:
+ if( ( HWND )lParam != hWnd )
+ {
+ 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()
+{
+ m_cKeysDown = 0;
+ ZeroMemory( m_aKeys, sizeof( BYTE ) * CAM_MAX_KEYS );
+ ZeroMemory( m_GamePad, sizeof( DXUT_GAMEPAD ) * DXUT_MAX_CONTROLLERS );
+
+ // 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;
+ ++m_cKeysDown;
+ }
+ }
+ 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 && ( DWORD )mappedKey < 8 )
+ {
+ m_aKeys[ mappedKey ] &= ~KEY_IS_DOWN_MASK;
+ --m_cKeysDown;
+ }
+ 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_CAPTURECHANGED:
+ {
+ if( ( HWND )lParam != hWnd )
+ {
+ if( ( m_nCurrentButtonMask & MOUSE_LEFT_BUTTON ) ||
+ ( m_nCurrentButtonMask & MOUSE_MIDDLE_BUTTON ) ||
+ ( m_nCurrentButtonMask & MOUSE_RIGHT_BUTTON ) )
+ {
+ m_bMouseLButtonDown = false;
+ m_bMouseMButtonDown = false;
+ m_bMouseRButtonDown = false;
+ m_nCurrentButtonMask &= ~MOUSE_LEFT_BUTTON;
+ m_nCurrentButtonMask &= ~MOUSE_MIDDLE_BUTTON;
+ m_nCurrentButtonMask &= ~MOUSE_RIGHT_BUTTON;
+ ReleaseCapture();
+ }
+ }
+ break;
+ }
+
+ case WM_MOUSEWHEEL:
+ // Update member var state
+ m_nMouseWheelDelta += ( short )HIWORD( wParam );
+ break;
+ }
+
+ return FALSE;
+}
+
+//--------------------------------------------------------------------------------------
+// Figure out the velocity based on keyboard input & drag if any
+//--------------------------------------------------------------------------------------
+void CBaseCamera::GetInput( bool bGetKeyboardInput, bool bGetMouseInput, bool bGetGamepadInput,
+ bool bResetCursorAfterMove )
+{
+ m_vKeyboardDirection = D3DXVECTOR3( 0, 0, 0 );
+ if( bGetKeyboardInput )
+ {
+ // Update acceleration vector based on keyboard state
+ if( IsKeyDown( m_aKeys[CAM_MOVE_FORWARD] ) )
+ m_vKeyboardDirection.z += 1.0f;
+ if( IsKeyDown( m_aKeys[CAM_MOVE_BACKWARD] ) )
+ m_vKeyboardDirection.z -= 1.0f;
+ if( m_bEnableYAxisMovement )
+ {
+ if( IsKeyDown( m_aKeys[CAM_MOVE_UP] ) )
+ m_vKeyboardDirection.y += 1.0f;
+ if( IsKeyDown( m_aKeys[CAM_MOVE_DOWN] ) )
+ m_vKeyboardDirection.y -= 1.0f;
+ }
+ if( IsKeyDown( m_aKeys[CAM_STRAFE_RIGHT] ) )
+ m_vKeyboardDirection.x += 1.0f;
+ if( IsKeyDown( m_aKeys[CAM_STRAFE_LEFT] ) )
+ m_vKeyboardDirection.x -= 1.0f;
+ }
+
+ if( bGetMouseInput )
+ {
+ UpdateMouseDelta();
+ }
+
+ if( bGetGamepadInput )
+ {
+ m_vGamePadLeftThumb = D3DXVECTOR3( 0, 0, 0 );
+ m_vGamePadRightThumb = D3DXVECTOR3( 0, 0, 0 );
+
+ // Get controller state
+ for( DWORD iUserIndex = 0; iUserIndex < DXUT_MAX_CONTROLLERS; iUserIndex++ )
+ {
+ DXUTGetGamepadState( iUserIndex, &m_GamePad[iUserIndex], true, true );
+
+ // Mark time if the controller is in a non-zero state
+ if( m_GamePad[iUserIndex].wButtons ||
+ m_GamePad[iUserIndex].sThumbLX || m_GamePad[iUserIndex].sThumbLX ||
+ m_GamePad[iUserIndex].sThumbRX || m_GamePad[iUserIndex].sThumbRY ||
+ m_GamePad[iUserIndex].bLeftTrigger || m_GamePad[iUserIndex].bRightTrigger )
+ {
+ m_GamePadLastActive[iUserIndex] = DXUTGetTime();
+ }
+ }
+
+ // Find out which controller was non-zero last
+ int iMostRecentlyActive = -1;
+ double fMostRecentlyActiveTime = 0.0f;
+ for( DWORD iUserIndex = 0; iUserIndex < DXUT_MAX_CONTROLLERS; iUserIndex++ )
+ {
+ if( m_GamePadLastActive[iUserIndex] > fMostRecentlyActiveTime )
+ {
+ fMostRecentlyActiveTime = m_GamePadLastActive[iUserIndex];
+ iMostRecentlyActive = iUserIndex;
+ }
+ }
+
+ // Use the most recent non-zero controller if its connected
+ if( iMostRecentlyActive >= 0 && m_GamePad[iMostRecentlyActive].bConnected )
+ {
+ m_vGamePadLeftThumb.x = m_GamePad[iMostRecentlyActive].fThumbLX;
+ m_vGamePadLeftThumb.y = 0.0f;
+ m_vGamePadLeftThumb.z = m_GamePad[iMostRecentlyActive].fThumbLY;
+
+ m_vGamePadRightThumb.x = m_GamePad[iMostRecentlyActive].fThumbRX;
+ m_vGamePadRightThumb.y = 0.0f;
+ m_vGamePadRightThumb.z = m_GamePad[iMostRecentlyActive].fThumbRY;
+ }
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+// Figure out the mouse delta based on mouse movement
+//--------------------------------------------------------------------------------------
+void CBaseCamera::UpdateMouseDelta()
+{
+ 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 && DXUTIsActive() )
+ {
+ // 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;
+
+ // Get the center of the current monitor
+ MONITORINFO mi;
+ mi.cbSize = sizeof( MONITORINFO );
+ DXUTGetMonitorInfo( DXUTMonitorFromWindow( DXUTGetHWND(), MONITOR_DEFAULTTONEAREST ), &mi );
+ ptCenter.x = ( mi.rcMonitor.left + mi.rcMonitor.right ) / 2;
+ ptCenter.y = ( mi.rcMonitor.top + mi.rcMonitor.bottom ) / 2;
+ SetCursorPos( ptCenter.x, ptCenter.y );
+ m_ptLastMousePosition = ptCenter;
+ }
+
+ // Smooth the relative mouse data over a few frames so it isn't
+ // jerky when moving slowly at low frame rates.
+ float fPercentOfNew = 1.0f / m_fFramesToSmoothMouseData;
+ float fPercentOfOld = 1.0f - fPercentOfNew;
+ m_vMouseDelta.x = m_vMouseDelta.x * fPercentOfOld + ptCurMouseDelta.x * fPercentOfNew;
+ m_vMouseDelta.y = m_vMouseDelta.y * fPercentOfOld + ptCurMouseDelta.y * fPercentOfNew;
+
+ m_vRotVelocity = m_vMouseDelta * m_fRotationScaler;
+}
+
+
+
+
+//--------------------------------------------------------------------------------------
+// Figure out the velocity based on keyboard input & drag if any
+//--------------------------------------------------------------------------------------
+void CBaseCamera::UpdateVelocity( float fElapsedTime )
+{
+ D3DXMATRIX mRotDelta;
+ D3DXVECTOR2 vGamePadRightThumb = D3DXVECTOR2( m_vGamePadRightThumb.x, -m_vGamePadRightThumb.z );
+ m_vRotVelocity = m_vMouseDelta * m_fRotationScaler + vGamePadRightThumb * 0.02f;
+
+ D3DXVECTOR3 vAccel = m_vKeyboardDirection + m_vGamePadLeftThumb;
+
+ // Normalize vector so if moving 2 dirs (left & forward),
+ // the camera doesn't move faster than if moving in 1 dir
+ D3DXVec3Normalize( &vAccel, &vAccel );
+
+ // Scale the acceleration vector
+ vAccel *= m_fMoveScaler;
+
+ if( m_bMovementDrag )
+ {
+ // Is there any acceleration this frame?
+ if( D3DXVec3LengthSq( &vAccel ) > 0 )
+ {
+ // If so, then this means the user has pressed a movement key\
+ // so change the velocity immediately to acceleration
+ // upon keyboard input. This isn't normal physics
+ // but it will give a quick response to keyboard input
+ m_vVelocity = vAccel;
+ m_fDragTimer = m_fTotalDragTimeToZero;
+ m_vVelocityDrag = vAccel / m_fDragTimer;
+ }
+ else
+ {
+ // If no key being pressed, then slowly decrease velocity to 0
+ if( m_fDragTimer > 0 )
+ {
+ // Drag until timer is <= 0
+ m_vVelocity -= m_vVelocityDrag * fElapsedTime;
+ m_fDragTimer -= fElapsedTime;
+ }
+ else
+ {
+ // Zero velocity
+ m_vVelocity = D3DXVECTOR3( 0, 0, 0 );
+ }
+ }
+ }
+ else
+ {
+ // No drag, so immediately change the velocity
+ m_vVelocity = vAccel;
+ }
+}
+
+
+
+
+//--------------------------------------------------------------------------------------
+// Clamps pV to lie inside m_vMinBoundary & m_vMaxBoundary
+//--------------------------------------------------------------------------------------
+void CBaseCamera::ConstrainToBoundary( D3DXVECTOR3* pV )
+{
+ // Constrain vector to a bounding box
+ pV->x = __max( pV->x, m_vMinBoundary.x );
+ pV->y = __max( pV->y, m_vMinBoundary.y );
+ pV->z = __max( pV->z, m_vMinBoundary.z );
+
+ pV->x = __min( pV->x, m_vMaxBoundary.x );
+ pV->y = __min( pV->y, m_vMaxBoundary.y );
+ pV->z = __min( pV->z, m_vMaxBoundary.z );
+}
+
+
+
+
+//--------------------------------------------------------------------------------------
+// Maps a windows virtual key to an enum
+//--------------------------------------------------------------------------------------
+D3DUtil_CameraKeys CBaseCamera::MapKey( UINT nKey )
+{
+ // This could be upgraded to a method that's user-definable but for
+ // simplicity, we'll use a hardcoded mapping.
+ switch( nKey )
+ {
+ case VK_CONTROL:
+ return CAM_CONTROLDOWN;
+ case VK_LEFT:
+ return CAM_STRAFE_LEFT;
+ case VK_RIGHT:
+ return CAM_STRAFE_RIGHT;
+ case VK_UP:
+ return CAM_MOVE_FORWARD;
+ case VK_DOWN:
+ return CAM_MOVE_BACKWARD;
+ case VK_PRIOR:
+ return CAM_MOVE_UP; // pgup
+ case VK_NEXT:
+ return CAM_MOVE_DOWN; // pgdn
+
+ case 'A':
+ return CAM_STRAFE_LEFT;
+ case 'D':
+ return CAM_STRAFE_RIGHT;
+ case 'W':
+ return CAM_MOVE_FORWARD;
+ case 'S':
+ return CAM_MOVE_BACKWARD;
+ case 'Q':
+ return CAM_MOVE_DOWN;
+ case 'E':
+ return CAM_MOVE_UP;
+
+ case VK_NUMPAD4:
+ return CAM_STRAFE_LEFT;
+ case VK_NUMPAD6:
+ return CAM_STRAFE_RIGHT;
+ case VK_NUMPAD8:
+ return CAM_MOVE_FORWARD;
+ case VK_NUMPAD2:
+ return CAM_MOVE_BACKWARD;
+ case VK_NUMPAD9:
+ return CAM_MOVE_UP;
+ case VK_NUMPAD3:
+ return CAM_MOVE_DOWN;
+
+ case VK_HOME:
+ return CAM_RESET;
+ }
+
+ return CAM_UNKNOWN;
+}
+
+
+
+
+//--------------------------------------------------------------------------------------
+// Reset the camera's position back to the default
+//--------------------------------------------------------------------------------------
+VOID CBaseCamera::Reset()
+{
+ SetViewParams( &m_vDefaultEye, &m_vDefaultLookAt );
+}
+
+
+
+
+//--------------------------------------------------------------------------------------
+// Constructor
+//--------------------------------------------------------------------------------------
+CFirstPersonCamera::CFirstPersonCamera() : m_nActiveButtonMask( 0x07 )
+{
+ m_bRotateWithoutButtonDown = false;
+}
+
+
+
+
+//--------------------------------------------------------------------------------------
+// Update the view matrix based on user input & elapsed time
+//--------------------------------------------------------------------------------------
+VOID CFirstPersonCamera::FrameMove( FLOAT fElapsedTime )
+{
+ if( DXUTGetGlobalTimer()->IsStopped() ) {
+ if (DXUTGetFPS() == 0.0f) fElapsedTime = 0;
+ else fElapsedTime = 1.0f / DXUTGetFPS();
+ }
+
+ if( IsKeyDown( m_aKeys[CAM_RESET] ) )
+ Reset();
+
+ // Get keyboard/mouse/gamepad input
+ GetInput( m_bEnablePositionMovement, ( m_nActiveButtonMask & m_nCurrentButtonMask ) || m_bRotateWithoutButtonDown,
+ true, m_bResetCursorAfterMove );
+
+ //// Get the mouse movement (if any) if the mouse button are down
+ //if( (m_nActiveButtonMask & m_nCurrentButtonMask) || m_bRotateWithoutButtonDown )
+ // UpdateMouseDelta( fElapsedTime );
+
+ // 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;
+
+ // If rotating the camera
+ if( ( m_nActiveButtonMask & m_nCurrentButtonMask ) ||
+ m_bRotateWithoutButtonDown ||
+ m_vGamePadRightThumb.x != 0 ||
+ m_vGamePadRightThumb.z != 0 )
+ {
+ // Update the pitch & yaw angle based on mouse movement
+ float fYawDelta = m_vRotVelocity.x;
+ float fPitchDelta = m_vRotVelocity.y;
+
+ // Invert pitch if requested
+ if( m_bInvertPitch )
+ fPitchDelta = -fPitchDelta;
+
+ m_fCameraPitchAngle += fPitchDelta;
+ m_fCameraYawAngle += fYawDelta;
+
+ // Limit pitch to straight up or straight down
+ m_fCameraPitchAngle = __max( -D3DX_PI / 2.0f, m_fCameraPitchAngle );
+ m_fCameraPitchAngle = __min( +D3DX_PI / 2.0f, m_fCameraPitchAngle );
+ }
+
+ // Make a rotation matrix based on the camera's yaw & pitch
+ D3DXMATRIX mCameraRot;
+ D3DXMatrixRotationYawPitchRoll( &mCameraRot, m_fCameraYawAngle, m_fCameraPitchAngle, 0 );
+
+ // 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;
+ 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 (0 == m_cKeysDown)
+ {
+ // Simulate motion for the video
+ m_WorldArcBall.OnBegin(0, 0);
+ m_WorldArcBall.OnMove(1, 1);
+ m_WorldArcBall.OnEnd();
+ }
+
+ 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;
+D3DXHANDLE CDXUTDirectionWidget::s_hRenderWith1LightNoTexture = NULL;
+D3DXHANDLE CDXUTDirectionWidget::s_hMaterialDiffuseColor = NULL;
+D3DXHANDLE CDXUTDirectionWidget::s_hLightDir = NULL;
+D3DXHANDLE CDXUTDirectionWidget::s_hWorldViewProjection = NULL;
+D3DXHANDLE CDXUTDirectionWidget::s_hWorld = 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"
+ " VS_OUTPUT Output;\r\n"
+ "\r\n"
+ " // Transform the position from object space to homogeneous projection space\r\n"
+ " Output.Position = mul(vPos, g_mWorldViewProjection);\r\n"
+ "\r\n"
+ " // Transform the normal from object space to world space\r\n"
+ " float3 vNormalWorldSpace;\r\n"
+ " vNormalWorldSpace = normalize(mul(vNormal, (float3x3)g_mWorld)); // normal (world space)\r\n"
+ "\r\n"
+ " // Compute simple directional lighting equation\r\n"
+ " Output.Diffuse.rgb = g_MaterialDiffuseColor * max(0,dot(vNormalWorldSpace, g_LightDir));\r\n"
+ " Output.Diffuse.a = 1.0f;\r\n"
+ "\r\n"
+ " return Output;\r\n"
+ "}\r\n"
+ "\r\n"
+ "float4 RenderWith1LightNoTexturePS( float4 Diffuse : COLOR0 ) : COLOR0\r\n"
+ "{\r\n"
+ " return Diffuse;\r\n"
+ "}\r\n"
+ "\r\n"
+ "technique RenderWith1LightNoTexture\r\n"
+ "{\r\n"
+ " pass P0\r\n"
+ " {\r\n"
+ " VertexShader = compile vs_2_0 RenderWith1LightNoTextureVS();\r\n"
+ " PixelShader = compile ps_2_0 RenderWith1LightNoTexturePS();\r\n"
+ " }\r\n"
+ "}\r\n"
+ "";
+
+ UINT dwBufferSize = ( UINT )strlen( g_strBuffer ) + 1;
+
+ DWORD Flags = D3DXFX_NOT_CLONEABLE;
+#ifdef D3DXFX_LARGEADDRESS_HANDLE
+ Flags |= D3DXFX_LARGEADDRESSAWARE;
+#endif
+
+ V_RETURN( D3DXCreateEffect( s_pd3d9Device, g_strBuffer, dwBufferSize, NULL, NULL, Flags,
+ NULL, &s_pD3D9Effect, NULL ) );
+
+ // Save technique handles for use when rendering
+ s_hRenderWith1LightNoTexture = s_pD3D9Effect->GetTechniqueByName( "RenderWith1LightNoTexture" );
+ s_hMaterialDiffuseColor = s_pD3D9Effect->GetParameterByName( NULL, "g_MaterialDiffuseColor" );
+ s_hLightDir = s_pD3D9Effect->GetParameterByName( NULL, "g_LightDir" );
+ s_hWorld = s_pD3D9Effect->GetParameterByName( NULL, "g_mWorld" );
+ s_hWorldViewProjection = s_pD3D9Effect->GetParameterByName( NULL, "g_mWorldViewProjection" );
+
+ // Load the mesh with D3DX and get back a ID3DXMesh*. For this
+ // sample we'll ignore the X file's embedded materials since we know
+ // exactly the model we're loading. See the mesh samples such as
+ // "OptimizedMesh" for a more generic mesh loading example.
+ V_RETURN( DXUTCreateArrowMeshFromInternalArray( s_pd3d9Device, &s_pD3D9Mesh ) );
+
+ // Optimize the mesh for this graphics card's vertex cache
+ // so when rendering the mesh's triangle list the vertices will
+ // cache hit more often so it won't have to re-execute the vertex shader
+ // on those vertices so it will improve perf.
+ DWORD* rgdwAdjacency = new DWORD[s_pD3D9Mesh->GetNumFaces() * 3];
+ if( rgdwAdjacency == NULL )
+ return E_OUTOFMEMORY;
+ V( s_pD3D9Mesh->GenerateAdjacency( 1e-6f, rgdwAdjacency ) );
+ V( s_pD3D9Mesh->OptimizeInplace( D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL ) );
+ delete []rgdwAdjacency;
+
+ return S_OK;
+}
+
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTDirectionWidget::OnD3D9ResetDevice( const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
+{
+ m_ArcBall.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
+ return S_OK;
+}
+
+
+//--------------------------------------------------------------------------------------
+void CDXUTDirectionWidget::StaticOnD3D9LostDevice()
+{
+ if( s_pD3D9Effect )
+ s_pD3D9Effect->OnLostDevice();
+}
+
+
+//--------------------------------------------------------------------------------------
+void CDXUTDirectionWidget::StaticOnD3D9DestroyDevice()
+{
+ SAFE_RELEASE( s_pD3D9Effect );
+ SAFE_RELEASE( s_pD3D9Mesh );
+}
+
+
+//--------------------------------------------------------------------------------------
+LRESULT CDXUTDirectionWidget::HandleMessages( HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam )
+{
+ switch( uMsg )
+ {
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ {
+ if( ( ( m_nRotateMask & MOUSE_LEFT_BUTTON ) != 0 && uMsg == WM_LBUTTONDOWN ) ||
+ ( ( m_nRotateMask & MOUSE_MIDDLE_BUTTON ) != 0 && uMsg == WM_MBUTTONDOWN ) ||
+ ( ( m_nRotateMask & MOUSE_RIGHT_BUTTON ) != 0 && uMsg == WM_RBUTTONDOWN ) )
+ {
+ int iMouseX = ( int )( short )LOWORD( lParam );
+ int iMouseY = ( int )( short )HIWORD( lParam );
+ m_ArcBall.OnBegin( iMouseX, iMouseY );
+ SetCapture( hWnd );
+ }
+ return TRUE;
+ }
+
+ case WM_MOUSEMOVE:
+ {
+ if( m_ArcBall.IsBeingDragged() )
+ {
+ int iMouseX = ( int )( short )LOWORD( lParam );
+ int iMouseY = ( int )( short )HIWORD( lParam );
+ m_ArcBall.OnMove( iMouseX, iMouseY );
+ UpdateLightDir();
+ }
+ return TRUE;
+ }
+
+ case WM_LBUTTONUP:
+ case WM_MBUTTONUP:
+ case WM_RBUTTONUP:
+ {
+ if( ( ( m_nRotateMask & MOUSE_LEFT_BUTTON ) != 0 && uMsg == WM_LBUTTONUP ) ||
+ ( ( m_nRotateMask & MOUSE_MIDDLE_BUTTON ) != 0 && uMsg == WM_MBUTTONUP ) ||
+ ( ( m_nRotateMask & MOUSE_RIGHT_BUTTON ) != 0 && uMsg == WM_RBUTTONUP ) )
+ {
+ m_ArcBall.OnEnd();
+ ReleaseCapture();
+ }
+
+ UpdateLightDir();
+ return TRUE;
+ }
+
+ case WM_CAPTURECHANGED:
+ {
+ if( ( HWND )lParam != hWnd )
+ {
+ if( ( m_nRotateMask & MOUSE_LEFT_BUTTON ) ||
+ ( m_nRotateMask & MOUSE_MIDDLE_BUTTON ) ||
+ ( m_nRotateMask & MOUSE_RIGHT_BUTTON ) )
+ {
+ m_ArcBall.OnEnd();
+ ReleaseCapture();
+ }
+ }
+ return TRUE;
+ }
+ }
+
+ return 0;
+}
+
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTDirectionWidget::OnRender9( D3DXCOLOR color, const D3DXMATRIX* pmView,
+ const D3DXMATRIX* pmProj, const D3DXVECTOR3* pEyePt )
+{
+ m_mView = *pmView;
+
+ // Render the light spheres so the user can visually see the light dir
+ UINT iPass, cPasses;
+ D3DXMATRIX mRotate;
+ D3DXMATRIX mScale;
+ D3DXMATRIX mTrans;
+ D3DXMATRIXA16 mWorldViewProj;
+ HRESULT hr;
+
+ V( s_pD3D9Effect->SetTechnique( s_hRenderWith1LightNoTexture ) );
+ V( s_pD3D9Effect->SetVector( s_hMaterialDiffuseColor, ( D3DXVECTOR4* )&color ) );
+
+ D3DXVECTOR3 vEyePt;
+ D3DXVec3Normalize( &vEyePt, pEyePt );
+ V( s_pD3D9Effect->SetValue( s_hLightDir, &vEyePt, sizeof( D3DXVECTOR3 ) ) );
+
+ // Rotate arrow model to point towards origin
+ D3DXMATRIX mRotateA, mRotateB;
+ D3DXVECTOR3 vAt = D3DXVECTOR3( 0, 0, 0 );
+ D3DXVECTOR3 vUp = D3DXVECTOR3( 0, 1, 0 );
+ D3DXMatrixRotationX( &mRotateB, D3DX_PI );
+ D3DXMatrixLookAtLH( &mRotateA, &m_vCurrentDir, &vAt, &vUp );
+ D3DXMatrixInverse( &mRotateA, NULL, &mRotateA );
+ mRotate = mRotateB * mRotateA;
+
+ D3DXVECTOR3 vL = m_vCurrentDir * m_fRadius * 1.0f;
+ D3DXMatrixTranslation( &mTrans, vL.x, vL.y, vL.z );
+ D3DXMatrixScaling( &mScale, m_fRadius * 0.2f, m_fRadius * 0.2f, m_fRadius * 0.2f );
+
+ D3DXMATRIX mWorld = mRotate * mScale * mTrans;
+ mWorldViewProj = mWorld * ( m_mView )*( *pmProj );
+
+ V( s_pD3D9Effect->SetMatrix( s_hWorldViewProjection, &mWorldViewProj ) );
+ V( s_pD3D9Effect->SetMatrix( s_hWorld, &mWorld ) );
+
+ for( int iSubset = 0; iSubset < 2; iSubset++ )
+ {
+ V( s_pD3D9Effect->Begin( &cPasses, 0 ) );
+ for( iPass = 0; iPass < cPasses; iPass++ )
+ {
+ V( s_pD3D9Effect->BeginPass( iPass ) );
+ V( s_pD3D9Mesh->DrawSubset( iSubset ) );
+ V( s_pD3D9Effect->EndPass() );
+ }
+ V( s_pD3D9Effect->End() );
+ }
+
+ return S_OK;
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTDirectionWidget::UpdateLightDir()
+{
+ D3DXMATRIX mInvView;
+ D3DXMatrixInverse( &mInvView, NULL, &m_mView );
+ mInvView._41 = mInvView._42 = mInvView._43 = 0;
+
+ D3DXMATRIX mLastRotInv;
+ D3DXMatrixInverse( &mLastRotInv, NULL, &m_mRotSnapshot );
+
+ D3DXMATRIX mRot = *m_ArcBall.GetRotationMatrix();
+ m_mRotSnapshot = mRot;
+
+ // 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.
+ m_mRot *= m_mView * mLastRotInv * mRot * mInvView;
+
+ // Since we're accumulating delta rotations, we need to orthonormalize
+ // the matrix to prevent eventual matrix skew
+ D3DXVECTOR3* pXBasis = ( D3DXVECTOR3* )&m_mRot._11;
+ D3DXVECTOR3* pYBasis = ( D3DXVECTOR3* )&m_mRot._21;
+ D3DXVECTOR3* pZBasis = ( D3DXVECTOR3* )&m_mRot._31;
+ D3DXVec3Normalize( pXBasis, pXBasis );
+ D3DXVec3Cross( pYBasis, pZBasis, pXBasis );
+ D3DXVec3Normalize( pYBasis, pYBasis );
+ D3DXVec3Cross( pZBasis, pXBasis, pYBasis );
+
+ // Transform the default direction vector by the light's rotation matrix
+ D3DXVec3TransformNormal( &m_vCurrentDir, &m_vDefaultDir, &m_mRot );
+
+ return S_OK;
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTDirectionWidget::StaticOnD3D11CreateDevice( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext )
+{
+
+
+ //s_pd3d10Device = pd3dDevice;
+
+ //const char* g_strBuffer =
+ // "float4 g_MaterialDiffuseColor; // Material's diffuse color\r\n"
+ // "float4 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 : SV_POSITION; // vertex position\r\n"
+ // " float4 Diffuse : COLOR0; // vertex diffuse color\r\n"
+ // "};\r\n"
+ // "\r\n"
+ // "VS_OUTPUT RenderWith1LightNoTextureVS( float3 vPos : POSITION,\r\n"
+ // " float3 vNormal : NORMAL )\r\n"
+ // "{\r\n"
+ // " VS_OUTPUT Output;\r\n"
+ // "\r\n"
+ // " // Transform the position from object space to homogeneous projection space\r\n"
+ // " Output.Position = mul( float4(vPos,1), g_mWorldViewProjection);\r\n"
+ // "\r\n"
+ // " // Transform the normal from object space to world space\r\n"
+ // " float3 vNormalWorldSpace;\r\n"
+ // " vNormalWorldSpace = normalize(mul(vNormal, (float3x3)g_mWorld)); // normal (world space)\r\n"
+ // "\r\n"
+ // " // Compute simple directional lighting equation\r\n"
+ // " Output.Diffuse.rgb = g_MaterialDiffuseColor * max(0,dot(vNormalWorldSpace, g_LightDir));\r\n"
+ // " Output.Diffuse.a = 1.0f;\r\n"
+ // "\r\n"
+ // " return Output;\r\n"
+ // "}\r\n"
+ // "\r\n"
+ // "float4 RenderWith1LightNoTexturePS( VS_OUTPUT Input ) : SV_TARGET\r\n"
+ // "{\r\n"
+ // " return Input.Diffuse;\r\n"
+ // "}\r\n"
+ // "\r\n"
+ // "technique10 RenderWith1LightNoTexture\r\n"
+ // "{\r\n"
+ // " pass p0\r\n"
+ // " {\r\n"
+ // " SetVertexShader( CompileShader( vs_4_0, RenderWith1LightNoTextureVS() ) );\r\n"
+ // " SetGeometryShader( NULL );\r\n"
+ // " SetPixelShader( CompileShader( ps_4_0, RenderWith1LightNoTexturePS() ) );\r\n"
+ // " }\r\n"
+ // "}\r\n"
+ // "";
+
+ //UINT dwBufferSize = ( UINT )strlen( g_strBuffer ) + 1;
+
+ //HRESULT hr = D3DX10CreateEffectFromMemory( g_strBuffer, dwBufferSize, "None", NULL, NULL, "fx_4_0",
+ // D3D10_SHADER_ENABLE_STRICTNESS, 0, pd3dDevice, NULL,
+ // NULL, &s_pD3D10Effect, NULL, NULL );
+ //if( FAILED( hr ) )
+ // return hr;
+
+ //s_pRenderTech = s_pD3D10Effect->GetTechniqueByName( "RenderWith1LightNoTexture" );
+ //g_pMaterialDiffuseColor = s_pD3D10Effect->GetVariableByName( "g_MaterialDiffuseColor" )->AsVector();
+ //g_pLightDir = s_pD3D10Effect->GetVariableByName( "g_LightDir" )->AsVector();
+ //g_pmWorld = s_pD3D10Effect->GetVariableByName( "g_mWorld" )->AsMatrix();
+ //g_pmWorldViewProjection = s_pD3D10Effect->GetVariableByName( "g_mWorldViewProjection" )->AsMatrix();
+
+ //const D3D10_INPUT_ELEMENT_DESC layout[] =
+ //{
+ // { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
+ // { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
+ //};
+ //D3D10_PASS_DESC PassDesc;
+ //V_RETURN( s_pRenderTech->GetPassByIndex( 0 )->GetDesc( &PassDesc ) );
+ //V_RETURN( pd3dDevice->CreateInputLayout( layout, 2, PassDesc.pIAInputSignature,
+ // PassDesc.IAInputSignatureSize, &s_pVertexLayout ) );
+
+ return S_OK;
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CDXUTDirectionWidget::OnRender11( D3DXCOLOR color, const D3DXMATRIX* pmView, const D3DXMATRIX* pmProj,
+ const D3DXVECTOR3* pEyePt )
+{
+ // NO 11 version of D3DX11Mesh YET
+ // m_mView = *pmView;
+
+ // // Render the light spheres so the user can visually see the light dir
+ // D3DXMATRIX mRotate;
+ // D3DXMATRIX mScale;
+ // D3DXMATRIX mTrans;
+ // D3DXMATRIXA16 mWorldViewProj;
+
+ // g_pMaterialDiffuseColor->SetFloatVector( ( float* )&color );
+ // D3DXVECTOR3 vEyePt;
+ // D3DXVec3Normalize( &vEyePt, pEyePt );
+ // g_pLightDir->SetFloatVector( ( float* )&vEyePt );
+
+ // // Rotate arrow model to point towards origin
+ // D3DXMATRIX mRotateA, mRotateB;
+ // D3DXVECTOR3 vAt = D3DXVECTOR3( 0, 0, 0 );
+ // D3DXVECTOR3 vUp = D3DXVECTOR3( 0, 1, 0 );
+ // D3DXMatrixRotationX( &mRotateB, D3DX_PI );
+ // D3DXMatrixLookAtLH( &mRotateA, &m_vCurrentDir, &vAt, &vUp );
+ // D3DXMatrixInverse( &mRotateA, NULL, &mRotateA );
+ // mRotate = mRotateB * mRotateA;
+
+ // D3DXVECTOR3 vL = m_vCurrentDir * m_fRadius * 1.0f;
+ // D3DXMatrixTranslation( &mTrans, vL.x, vL.y, vL.z );
+ // D3DXMatrixScaling( &mScale, m_fRadius * 0.2f, m_fRadius * 0.2f, m_fRadius * 0.2f );
+
+ // D3DXMATRIX mWorld = mRotate * mScale * mTrans;
+ // mWorldViewProj = mWorld * ( m_mView )*( *pmProj );
+
+ // g_pmWorldViewProjection->SetMatrix( ( float* )&mWorldViewProj );
+ // g_pmWorld->SetMatrix( ( float* )&mWorld );
+
+ // s_pd3d10Device->IASetInputLayout( s_pVertexLayout );
+
+ // Add rendering code here
+
+ return S_OK;
+}
+
+//--------------------------------------------------------------------------------------
+void CDXUTDirectionWidget::StaticOnD3D11DestroyDevice()
+{
+// SAFE_RELEASE( s_pVertexLayout );
+// SAFE_RELEASE( s_pD3D11Effect );
+}