DXUTmisc.cpp
上传用户:junlon
上传日期:2022-01-05
资源大小:39075k
文件大小:130k
源码类别:

DirextX编程

开发平台:

Visual C++

  1. //--------------------------------------------------------------------------------------
  2. // Clamps pV to lie inside m_vMinBoundary & m_vMaxBoundary
  3. //--------------------------------------------------------------------------------------
  4. void CBaseCamera::ConstrainToBoundary( D3DXVECTOR3* pV )
  5. {
  6.     // Constrain vector to a bounding box 
  7.     pV->x = __max(pV->x, m_vMinBoundary.x);
  8.     pV->y = __max(pV->y, m_vMinBoundary.y);
  9.     pV->z = __max(pV->z, m_vMinBoundary.z);
  10.     pV->x = __min(pV->x, m_vMaxBoundary.x);
  11.     pV->y = __min(pV->y, m_vMaxBoundary.y);
  12.     pV->z = __min(pV->z, m_vMaxBoundary.z);
  13. }
  14. //--------------------------------------------------------------------------------------
  15. // Maps a windows virtual key to an enum
  16. //--------------------------------------------------------------------------------------
  17. D3DUtil_CameraKeys CBaseCamera::MapKey( UINT nKey )
  18. {
  19.     // This could be upgraded to a method that's user-definable but for 
  20.     // simplicity, we'll use a hardcoded mapping.
  21.     switch( nKey )
  22.     {
  23.         case VK_CONTROL:  return CAM_CONTROLDOWN;
  24.         case VK_LEFT:  return CAM_STRAFE_LEFT;
  25.         case VK_RIGHT: return CAM_STRAFE_RIGHT;
  26.         case VK_UP:    return CAM_MOVE_FORWARD;
  27.         case VK_DOWN:  return CAM_MOVE_BACKWARD;
  28.         case VK_PRIOR: return CAM_MOVE_UP;        // pgup
  29.         case VK_NEXT:  return CAM_MOVE_DOWN;      // pgdn
  30.         case 'A':      return CAM_STRAFE_LEFT;
  31.         case 'D':      return CAM_STRAFE_RIGHT;
  32.         case 'W':      return CAM_MOVE_FORWARD;
  33.         case 'S':      return CAM_MOVE_BACKWARD;
  34.         case 'Q':      return CAM_MOVE_DOWN;
  35.         case 'E':      return CAM_MOVE_UP;
  36.         case VK_NUMPAD4: return CAM_STRAFE_LEFT;
  37.         case VK_NUMPAD6: return CAM_STRAFE_RIGHT;
  38.         case VK_NUMPAD8: return CAM_MOVE_FORWARD;
  39.         case VK_NUMPAD2: return CAM_MOVE_BACKWARD;
  40.         case VK_NUMPAD9: return CAM_MOVE_UP;        
  41.         case VK_NUMPAD3: return CAM_MOVE_DOWN;      
  42.         case VK_HOME:   return CAM_RESET;
  43.     }
  44.     return CAM_UNKNOWN;
  45. }
  46. //--------------------------------------------------------------------------------------
  47. // Reset the camera's position back to the default
  48. //--------------------------------------------------------------------------------------
  49. VOID CBaseCamera::Reset()
  50. {
  51.     SetViewParams( &m_vDefaultEye, &m_vDefaultLookAt );
  52. }
  53. //--------------------------------------------------------------------------------------
  54. // Constructor
  55. //--------------------------------------------------------------------------------------
  56. CFirstPersonCamera::CFirstPersonCamera() :
  57.     m_nActiveButtonMask( 0x07 )
  58. {
  59.     m_bRotateWithoutButtonDown = false;
  60. }
  61. //--------------------------------------------------------------------------------------
  62. // Update the view matrix based on user input & elapsed time
  63. //--------------------------------------------------------------------------------------
  64. VOID CFirstPersonCamera::FrameMove( FLOAT fElapsedTime )
  65. {
  66.     if( DXUTGetGlobalTimer()->IsStopped() )
  67.         fElapsedTime = 1.0f / DXUTGetFPS();
  68.     if( IsKeyDown(m_aKeys[CAM_RESET]) )
  69.         Reset();
  70.     // Get keyboard/mouse/gamepad input
  71.     GetInput( m_bEnablePositionMovement, (m_nActiveButtonMask & m_nCurrentButtonMask) || m_bRotateWithoutButtonDown, true, m_bResetCursorAfterMove );
  72.     // Get amount of velocity based on the keyboard input and drag (if any)
  73.     UpdateVelocity( fElapsedTime );
  74.     // Simple euler method to calculate position delta
  75.     D3DXVECTOR3 vPosDelta = m_vVelocity * fElapsedTime;
  76.     // If rotating the camera 
  77.     if( (m_nActiveButtonMask & m_nCurrentButtonMask) || 
  78.         m_bRotateWithoutButtonDown || 
  79.         m_vGamePadRightThumb.x != 0 || 
  80.         m_vGamePadRightThumb.z != 0 )
  81.     {
  82.         // Update the pitch & yaw angle based on mouse movement
  83.         float fYawDelta   = m_vRotVelocity.x;
  84.         float fPitchDelta = m_vRotVelocity.y;
  85.         // Invert pitch if requested
  86.         if( m_bInvertPitch )
  87.             fPitchDelta = -fPitchDelta;
  88.         m_fCameraPitchAngle += fPitchDelta;
  89.         m_fCameraYawAngle   += fYawDelta;
  90.         // Limit pitch to straight up or straight down
  91.         m_fCameraPitchAngle = __max( -D3DX_PI/2.0f,  m_fCameraPitchAngle );
  92.         m_fCameraPitchAngle = __min( +D3DX_PI/2.0f,  m_fCameraPitchAngle );
  93.     }
  94.     // Make a rotation matrix based on the camera's yaw & pitch
  95.     D3DXMATRIX mCameraRot;
  96.     D3DXMatrixRotationYawPitchRoll( &mCameraRot, m_fCameraYawAngle, m_fCameraPitchAngle, 0 );
  97.     // Transform vectors based on camera's rotation matrix
  98.     D3DXVECTOR3 vWorldUp, vWorldAhead;
  99.     D3DXVECTOR3 vLocalUp    = D3DXVECTOR3(0,1,0);
  100.     D3DXVECTOR3 vLocalAhead = D3DXVECTOR3(0,0,1);
  101.     D3DXVec3TransformCoord( &vWorldUp, &vLocalUp, &mCameraRot );
  102.     D3DXVec3TransformCoord( &vWorldAhead, &vLocalAhead, &mCameraRot );
  103.     // Transform the position delta by the camera's rotation 
  104.     D3DXVECTOR3 vPosDeltaWorld;
  105.     if( !m_bEnableYAxisMovement )
  106.     {
  107.         // If restricting Y movement, do not include pitch
  108.         // when transforming position delta vector.
  109.         D3DXMatrixRotationYawPitchRoll( &mCameraRot, m_fCameraYawAngle, 0.0f, 0.0f );
  110.     }
  111.     D3DXVec3TransformCoord( &vPosDeltaWorld, &vPosDelta, &mCameraRot );
  112.     // Move the eye position 
  113.     m_vEye += vPosDeltaWorld;
  114.     if( m_bClipToBoundary )
  115.         ConstrainToBoundary( &m_vEye );
  116.     // Update the lookAt position based on the eye position 
  117.     m_vLookAt = m_vEye + vWorldAhead;
  118.     // Update the view matrix
  119.     D3DXMatrixLookAtLH( &m_mView, &m_vEye, &m_vLookAt, &vWorldUp );
  120.     D3DXMatrixInverse( &m_mCameraWorld, NULL, &m_mView );
  121. }
  122. //--------------------------------------------------------------------------------------
  123. // Enable or disable each of the mouse buttons for rotation drag.
  124. //--------------------------------------------------------------------------------------
  125. void CFirstPersonCamera::SetRotateButtons( bool bLeft, bool bMiddle, bool bRight, bool bRotateWithoutButtonDown )
  126. {
  127.     m_nActiveButtonMask = ( bLeft ? MOUSE_LEFT_BUTTON : 0 ) |
  128.                           ( bMiddle ? MOUSE_MIDDLE_BUTTON : 0 ) |
  129.                           ( bRight ? MOUSE_RIGHT_BUTTON : 0 );
  130.     m_bRotateWithoutButtonDown = bRotateWithoutButtonDown;
  131. }
  132. //--------------------------------------------------------------------------------------
  133. // Constructor 
  134. //--------------------------------------------------------------------------------------
  135. CModelViewerCamera::CModelViewerCamera()
  136. {
  137.     D3DXMatrixIdentity( &m_mWorld );
  138.     D3DXMatrixIdentity( &m_mModelRot );
  139.     D3DXMatrixIdentity( &m_mModelLastRot );    
  140.     D3DXMatrixIdentity( &m_mCameraRotLast );    
  141.     m_vModelCenter = D3DXVECTOR3(0,0,0);
  142.     m_fRadius    = 5.0f;
  143.     m_fDefaultRadius = 5.0f;
  144.     m_fMinRadius = 1.0f;
  145.     m_fMaxRadius = FLT_MAX;
  146.     m_bLimitPitch = false;
  147.     m_bEnablePositionMovement = false;
  148.     m_bAttachCameraToModel = false;
  149.     m_nRotateModelButtonMask  = MOUSE_LEFT_BUTTON;
  150.     m_nZoomButtonMask         = MOUSE_WHEEL;
  151.     m_nRotateCameraButtonMask = MOUSE_RIGHT_BUTTON;
  152.     m_bDragSinceLastUpdate    = true;
  153. }
  154. //--------------------------------------------------------------------------------------
  155. // Update the view matrix & the model's world matrix based 
  156. //       on user input & elapsed time
  157. //--------------------------------------------------------------------------------------
  158. VOID CModelViewerCamera::FrameMove( FLOAT fElapsedTime )
  159. {
  160.     if( IsKeyDown(m_aKeys[CAM_RESET]) )
  161.         Reset();
  162.     // If no dragged has happend since last time FrameMove is called,
  163.     // and no camera key is held down, then no need to handle again.
  164.     if( !m_bDragSinceLastUpdate && 0 == m_cKeysDown )
  165.         return;
  166.     m_bDragSinceLastUpdate = false;
  167.     // Get keyboard/mouse/gamepad input
  168.     GetInput( m_bEnablePositionMovement, m_nCurrentButtonMask != 0, true, false );
  169.     // Get amount of velocity based on the keyboard input and drag (if any)
  170.     UpdateVelocity( fElapsedTime );
  171.     // Simple euler method to calculate position delta
  172.     D3DXVECTOR3 vPosDelta = m_vVelocity * fElapsedTime;
  173.     // Change the radius from the camera to the model based on wheel scrolling
  174.     if( m_nMouseWheelDelta && m_nZoomButtonMask == MOUSE_WHEEL )
  175.         m_fRadius -= m_nMouseWheelDelta * m_fRadius * 0.1f;
  176.     m_fRadius = __min( m_fMaxRadius, m_fRadius );
  177.     m_fRadius = __max( m_fMinRadius, m_fRadius );
  178.     m_nMouseWheelDelta = 0;
  179.     // Get the inverse of the arcball's rotation matrix
  180.     D3DXMATRIX mCameraRot;
  181.     D3DXMatrixInverse( &mCameraRot, NULL, m_ViewArcBall.GetRotationMatrix() );
  182.     // Transform vectors based on camera's rotation matrix
  183.     D3DXVECTOR3 vWorldUp, vWorldAhead;
  184.     D3DXVECTOR3 vLocalUp    = D3DXVECTOR3(0,1,0);
  185.     D3DXVECTOR3 vLocalAhead = D3DXVECTOR3(0,0,1);
  186.     D3DXVec3TransformCoord( &vWorldUp, &vLocalUp, &mCameraRot );
  187.     D3DXVec3TransformCoord( &vWorldAhead, &vLocalAhead, &mCameraRot );
  188.     // Transform the position delta by the camera's rotation 
  189.     D3DXVECTOR3 vPosDeltaWorld;
  190.     D3DXVec3TransformCoord( &vPosDeltaWorld, &vPosDelta, &mCameraRot );
  191.     // Move the lookAt position 
  192.     m_vLookAt += vPosDeltaWorld;
  193.     if( m_bClipToBoundary )
  194.         ConstrainToBoundary( &m_vLookAt );
  195.     // Update the eye point based on a radius away from the lookAt position
  196.     m_vEye = m_vLookAt - vWorldAhead * m_fRadius;
  197.     // Update the view matrix
  198.     D3DXMatrixLookAtLH( &m_mView, &m_vEye, &m_vLookAt, &vWorldUp );
  199.     D3DXMATRIX mInvView;
  200.     D3DXMatrixInverse( &mInvView, NULL, &m_mView );
  201.     mInvView._41 = mInvView._42 = mInvView._43 = 0;
  202.     D3DXMATRIX mModelLastRotInv;
  203.     D3DXMatrixInverse(&mModelLastRotInv, NULL, &m_mModelLastRot);
  204.     // Accumulate the delta of the arcball's rotation in view space.
  205.     // Note that per-frame delta rotations could be problematic over long periods of time.
  206.     D3DXMATRIX mModelRot;
  207.     mModelRot = *m_WorldArcBall.GetRotationMatrix();
  208.     m_mModelRot *= m_mView * mModelLastRotInv * mModelRot * mInvView;
  209.     if( m_ViewArcBall.IsBeingDragged() && m_bAttachCameraToModel && !IsKeyDown(m_aKeys[CAM_CONTROLDOWN]) )
  210.     {
  211.         // Attach camera to model by inverse of the model rotation
  212.         D3DXMATRIX mCameraLastRotInv;
  213.         D3DXMatrixInverse(&mCameraLastRotInv, NULL, &m_mCameraRotLast);
  214.         D3DXMATRIX mCameraRotDelta = mCameraLastRotInv * mCameraRot; // local to world matrix
  215.         m_mModelRot *= mCameraRotDelta;
  216.     }
  217.     m_mCameraRotLast = mCameraRot; 
  218.     m_mModelLastRot = mModelRot;
  219.     // Since we're accumulating delta rotations, we need to orthonormalize 
  220.     // the matrix to prevent eventual matrix skew
  221.     D3DXVECTOR3* pXBasis = (D3DXVECTOR3*) &m_mModelRot._11;
  222.     D3DXVECTOR3* pYBasis = (D3DXVECTOR3*) &m_mModelRot._21;
  223.     D3DXVECTOR3* pZBasis = (D3DXVECTOR3*) &m_mModelRot._31;
  224.     D3DXVec3Normalize( pXBasis, pXBasis );
  225.     D3DXVec3Cross( pYBasis, pZBasis, pXBasis );
  226.     D3DXVec3Normalize( pYBasis, pYBasis );
  227.     D3DXVec3Cross( pZBasis, pXBasis, pYBasis );
  228.     // Translate the rotation matrix to the same position as the lookAt position
  229.     m_mModelRot._41 = m_vLookAt.x;
  230.     m_mModelRot._42 = m_vLookAt.y;
  231.     m_mModelRot._43 = m_vLookAt.z;
  232.     // Translate world matrix so its at the center of the model
  233.     D3DXMATRIX mTrans;
  234.     D3DXMatrixTranslation( &mTrans, -m_vModelCenter.x, -m_vModelCenter.y, -m_vModelCenter.z );
  235.     m_mWorld = mTrans * m_mModelRot;
  236. }
  237. void CModelViewerCamera::SetDragRect( RECT &rc )
  238. {
  239.     CBaseCamera::SetDragRect( rc );
  240.     m_WorldArcBall.SetOffset( rc.left, rc.top );
  241.     m_ViewArcBall.SetOffset( rc.left, rc.top );
  242.     SetWindow( rc.right - rc.left, rc.bottom - rc.top );
  243. }
  244. //--------------------------------------------------------------------------------------
  245. // Reset the camera's position back to the default
  246. //--------------------------------------------------------------------------------------
  247. VOID CModelViewerCamera::Reset()
  248. {
  249.     CBaseCamera::Reset();
  250.     D3DXMatrixIdentity( &m_mWorld );
  251.     D3DXMatrixIdentity( &m_mModelRot );
  252.     D3DXMatrixIdentity( &m_mModelLastRot );    
  253.     D3DXMatrixIdentity( &m_mCameraRotLast );    
  254.     m_fRadius = m_fDefaultRadius;
  255.     m_WorldArcBall.Reset();
  256.     m_ViewArcBall.Reset();
  257. }
  258. //--------------------------------------------------------------------------------------
  259. // Override for setting the view parameters
  260. //--------------------------------------------------------------------------------------
  261. void CModelViewerCamera::SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt )
  262. {
  263.     CBaseCamera::SetViewParams( pvEyePt, pvLookatPt );
  264.     // Propogate changes to the member arcball
  265.     D3DXQUATERNION quat;
  266.     D3DXMATRIXA16 mRotation;
  267.     D3DXVECTOR3 vUp(0,1,0);
  268.     D3DXMatrixLookAtLH( &mRotation, pvEyePt, pvLookatPt, &vUp );
  269.     D3DXQuaternionRotationMatrix( &quat, &mRotation );
  270.     m_ViewArcBall.SetQuatNow( quat );
  271.     // Set the radius according to the distance
  272.     D3DXVECTOR3 vEyeToPoint;
  273.     D3DXVec3Subtract( &vEyeToPoint, pvLookatPt, pvEyePt );
  274.     SetRadius( D3DXVec3Length( &vEyeToPoint ) );
  275.     // View information changed. FrameMove should be called.
  276.     m_bDragSinceLastUpdate = true;
  277. }
  278. void CModelViewerCamera::SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt, D3DXVECTOR3* pvUpVec )
  279. {
  280.     CBaseCamera::SetViewParams( pvEyePt, pvLookatPt, pvUpVec );
  281.     // Propogate changes to the member arcball
  282.     D3DXQUATERNION quat;
  283.     D3DXMATRIXA16 mRotation;
  284. //    D3DXVECTOR3 vUp(0,1,0);
  285.     D3DXMatrixLookAtLH( &mRotation, pvEyePt, pvLookatPt, pvUpVec );
  286.     D3DXQuaternionRotationMatrix( &quat, &mRotation );
  287.     m_ViewArcBall.SetQuatNow( quat );
  288.     // Set the radius according to the distance
  289.     D3DXVECTOR3 vEyeToPoint;
  290.     D3DXVec3Subtract( &vEyeToPoint, pvLookatPt, pvEyePt );
  291.     SetRadius( D3DXVec3Length( &vEyeToPoint ) );
  292.     // View information changed. FrameMove should be called.
  293.     m_bDragSinceLastUpdate = true;
  294. }
  295. //--------------------------------------------------------------------------------------
  296. // Call this from your message proc so this class can handle window messages
  297. //--------------------------------------------------------------------------------------
  298. LRESULT CModelViewerCamera::HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  299. {
  300.     CBaseCamera::HandleMessages( hWnd, uMsg, wParam, lParam );
  301.     if( ( (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_LEFT_BUTTON) ||
  302.         ( (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_MIDDLE_BUTTON) ||
  303.         ( (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_RIGHT_BUTTON) )
  304.     {
  305.         int iMouseX = (short)LOWORD(lParam);
  306.         int iMouseY = (short)HIWORD(lParam);
  307.         m_WorldArcBall.OnBegin( iMouseX, iMouseY );
  308.     }
  309.     if( ( (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) && m_nRotateCameraButtonMask & MOUSE_LEFT_BUTTON) ||
  310.         ( (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) && m_nRotateCameraButtonMask & MOUSE_MIDDLE_BUTTON) ||
  311.         ( (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) && m_nRotateCameraButtonMask & MOUSE_RIGHT_BUTTON) )
  312.     {
  313.         int iMouseX = (short)LOWORD(lParam);
  314.         int iMouseY = (short)HIWORD(lParam);
  315.         m_ViewArcBall.OnBegin( iMouseX, iMouseY );
  316.     }
  317.     if( uMsg == WM_MOUSEMOVE )
  318.     {
  319.         int iMouseX = (short)LOWORD(lParam);
  320.         int iMouseY = (short)HIWORD(lParam);
  321.         m_WorldArcBall.OnMove( iMouseX, iMouseY );
  322.         m_ViewArcBall.OnMove( iMouseX, iMouseY );
  323.     }
  324.     if( (uMsg == WM_LBUTTONUP && m_nRotateModelButtonMask & MOUSE_LEFT_BUTTON) ||
  325.         (uMsg == WM_MBUTTONUP && m_nRotateModelButtonMask & MOUSE_MIDDLE_BUTTON) ||
  326.         (uMsg == WM_RBUTTONUP && m_nRotateModelButtonMask & MOUSE_RIGHT_BUTTON) )
  327.     {
  328.         m_WorldArcBall.OnEnd();
  329.     }
  330.     if( (uMsg == WM_LBUTTONUP && m_nRotateCameraButtonMask & MOUSE_LEFT_BUTTON) ||
  331.         (uMsg == WM_MBUTTONUP && m_nRotateCameraButtonMask & MOUSE_MIDDLE_BUTTON) ||
  332.         (uMsg == WM_RBUTTONUP && m_nRotateCameraButtonMask & MOUSE_RIGHT_BUTTON) )
  333.     {
  334.         m_ViewArcBall.OnEnd();
  335.     }
  336.     if( uMsg == WM_CAPTURECHANGED )
  337.     {
  338.         if( (HWND)lParam != hWnd )
  339.         {
  340.             if( (m_nRotateModelButtonMask & MOUSE_LEFT_BUTTON) ||
  341.                 (m_nRotateModelButtonMask & MOUSE_MIDDLE_BUTTON) ||
  342.                 (m_nRotateModelButtonMask & MOUSE_RIGHT_BUTTON) )
  343.             {
  344.                 m_WorldArcBall.OnEnd();
  345.             }
  346.         
  347.             if( (m_nRotateCameraButtonMask & MOUSE_LEFT_BUTTON) ||
  348.                 (m_nRotateCameraButtonMask & MOUSE_MIDDLE_BUTTON) ||
  349.                 (m_nRotateCameraButtonMask & MOUSE_RIGHT_BUTTON) )
  350.             {
  351.                 m_ViewArcBall.OnEnd();
  352.             }
  353.         }
  354.     }
  355.     if( uMsg == WM_LBUTTONDOWN ||
  356.         uMsg == WM_LBUTTONDBLCLK ||
  357.         uMsg == WM_MBUTTONDOWN ||
  358.         uMsg == WM_MBUTTONDBLCLK ||
  359.         uMsg == WM_RBUTTONDOWN ||
  360.         uMsg == WM_RBUTTONDBLCLK ||
  361.         uMsg == WM_LBUTTONUP ||
  362.         uMsg == WM_MBUTTONUP ||
  363.         uMsg == WM_RBUTTONUP ||
  364.         uMsg == WM_MOUSEWHEEL ||
  365.         uMsg == WM_MOUSEMOVE )
  366.     {
  367.         m_bDragSinceLastUpdate = true;
  368.     }
  369.     return FALSE;
  370. }
  371. //--------------------------------------------------------------------------------------
  372. // Desc: Returns a view matrix for rendering to a face of a cubemap.
  373. //--------------------------------------------------------------------------------------
  374. D3DXMATRIX DXUTGetCubeMapViewMatrix( DWORD dwFace )
  375. {
  376.     D3DXVECTOR3 vEyePt   = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  377.     D3DXVECTOR3 vLookDir;
  378.     D3DXVECTOR3 vUpDir;
  379.     switch( dwFace )
  380.     {
  381.         case D3DCUBEMAP_FACE_POSITIVE_X:
  382.             vLookDir = D3DXVECTOR3( 1.0f, 0.0f, 0.0f );
  383.             vUpDir   = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  384.             break;
  385.         case D3DCUBEMAP_FACE_NEGATIVE_X:
  386.             vLookDir = D3DXVECTOR3(-1.0f, 0.0f, 0.0f );
  387.             vUpDir   = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  388.             break;
  389.         case D3DCUBEMAP_FACE_POSITIVE_Y:
  390.             vLookDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  391.             vUpDir   = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );
  392.             break;
  393.         case D3DCUBEMAP_FACE_NEGATIVE_Y:
  394.             vLookDir = D3DXVECTOR3( 0.0f,-1.0f, 0.0f );
  395.             vUpDir   = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
  396.             break;
  397.         case D3DCUBEMAP_FACE_POSITIVE_Z:
  398.             vLookDir = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
  399.             vUpDir   = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  400.             break;
  401.         case D3DCUBEMAP_FACE_NEGATIVE_Z:
  402.             vLookDir = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );
  403.             vUpDir   = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  404.             break;
  405.     }
  406.     // Set the view transform for this cubemap surface
  407.     D3DXMATRIXA16 mView;
  408.     D3DXMatrixLookAtLH( &mView, &vEyePt, &vLookDir, &vUpDir );
  409.     return mView;
  410. }
  411. //--------------------------------------------------------------------------------------
  412. // Returns the string for the given D3DFORMAT.
  413. //--------------------------------------------------------------------------------------
  414. LPCWSTR DXUTD3DFormatToString( D3DFORMAT format, bool bWithPrefix )
  415. {
  416.     WCHAR* pstr = NULL;
  417.     switch( format )
  418.     {
  419.     case D3DFMT_UNKNOWN:         pstr = L"D3DFMT_UNKNOWN"; break;
  420.     case D3DFMT_R8G8B8:          pstr = L"D3DFMT_R8G8B8"; break;
  421.     case D3DFMT_A8R8G8B8:        pstr = L"D3DFMT_A8R8G8B8"; break;
  422.     case D3DFMT_X8R8G8B8:        pstr = L"D3DFMT_X8R8G8B8"; break;
  423.     case D3DFMT_R5G6B5:          pstr = L"D3DFMT_R5G6B5"; break;
  424.     case D3DFMT_X1R5G5B5:        pstr = L"D3DFMT_X1R5G5B5"; break;
  425.     case D3DFMT_A1R5G5B5:        pstr = L"D3DFMT_A1R5G5B5"; break;
  426.     case D3DFMT_A4R4G4B4:        pstr = L"D3DFMT_A4R4G4B4"; break;
  427.     case D3DFMT_R3G3B2:          pstr = L"D3DFMT_R3G3B2"; break;
  428.     case D3DFMT_A8:              pstr = L"D3DFMT_A8"; break;
  429.     case D3DFMT_A8R3G3B2:        pstr = L"D3DFMT_A8R3G3B2"; break;
  430.     case D3DFMT_X4R4G4B4:        pstr = L"D3DFMT_X4R4G4B4"; break;
  431.     case D3DFMT_A2B10G10R10:     pstr = L"D3DFMT_A2B10G10R10"; break;
  432.     case D3DFMT_A8B8G8R8:        pstr = L"D3DFMT_A8B8G8R8"; break;
  433.     case D3DFMT_X8B8G8R8:        pstr = L"D3DFMT_X8B8G8R8"; break;
  434.     case D3DFMT_G16R16:          pstr = L"D3DFMT_G16R16"; break;
  435.     case D3DFMT_A2R10G10B10:     pstr = L"D3DFMT_A2R10G10B10"; break;
  436.     case D3DFMT_A16B16G16R16:    pstr = L"D3DFMT_A16B16G16R16"; break;
  437.     case D3DFMT_A8P8:            pstr = L"D3DFMT_A8P8"; break;
  438.     case D3DFMT_P8:              pstr = L"D3DFMT_P8"; break;
  439.     case D3DFMT_L8:              pstr = L"D3DFMT_L8"; break;
  440.     case D3DFMT_A8L8:            pstr = L"D3DFMT_A8L8"; break;
  441.     case D3DFMT_A4L4:            pstr = L"D3DFMT_A4L4"; break;
  442.     case D3DFMT_V8U8:            pstr = L"D3DFMT_V8U8"; break;
  443.     case D3DFMT_L6V5U5:          pstr = L"D3DFMT_L6V5U5"; break;
  444.     case D3DFMT_X8L8V8U8:        pstr = L"D3DFMT_X8L8V8U8"; break;
  445.     case D3DFMT_Q8W8V8U8:        pstr = L"D3DFMT_Q8W8V8U8"; break;
  446.     case D3DFMT_V16U16:          pstr = L"D3DFMT_V16U16"; break;
  447.     case D3DFMT_A2W10V10U10:     pstr = L"D3DFMT_A2W10V10U10"; break;
  448.     case D3DFMT_UYVY:            pstr = L"D3DFMT_UYVY"; break;
  449.     case D3DFMT_YUY2:            pstr = L"D3DFMT_YUY2"; break;
  450.     case D3DFMT_DXT1:            pstr = L"D3DFMT_DXT1"; break;
  451.     case D3DFMT_DXT2:            pstr = L"D3DFMT_DXT2"; break;
  452.     case D3DFMT_DXT3:            pstr = L"D3DFMT_DXT3"; break;
  453.     case D3DFMT_DXT4:            pstr = L"D3DFMT_DXT4"; break;
  454.     case D3DFMT_DXT5:            pstr = L"D3DFMT_DXT5"; break;
  455.     case D3DFMT_D16_LOCKABLE:    pstr = L"D3DFMT_D16_LOCKABLE"; break;
  456.     case D3DFMT_D32:             pstr = L"D3DFMT_D32"; break;
  457.     case D3DFMT_D15S1:           pstr = L"D3DFMT_D15S1"; break;
  458.     case D3DFMT_D24S8:           pstr = L"D3DFMT_D24S8"; break;
  459.     case D3DFMT_D24X8:           pstr = L"D3DFMT_D24X8"; break;
  460.     case D3DFMT_D24X4S4:         pstr = L"D3DFMT_D24X4S4"; break;
  461.     case D3DFMT_D16:             pstr = L"D3DFMT_D16"; break;
  462.     case D3DFMT_L16:             pstr = L"D3DFMT_L16"; break;
  463.     case D3DFMT_VERTEXDATA:      pstr = L"D3DFMT_VERTEXDATA"; break;
  464.     case D3DFMT_INDEX16:         pstr = L"D3DFMT_INDEX16"; break;
  465.     case D3DFMT_INDEX32:         pstr = L"D3DFMT_INDEX32"; break;
  466.     case D3DFMT_Q16W16V16U16:    pstr = L"D3DFMT_Q16W16V16U16"; break;
  467.     case D3DFMT_MULTI2_ARGB8:    pstr = L"D3DFMT_MULTI2_ARGB8"; break;
  468.     case D3DFMT_R16F:            pstr = L"D3DFMT_R16F"; break;
  469.     case D3DFMT_G16R16F:         pstr = L"D3DFMT_G16R16F"; break;
  470.     case D3DFMT_A16B16G16R16F:   pstr = L"D3DFMT_A16B16G16R16F"; break;
  471.     case D3DFMT_R32F:            pstr = L"D3DFMT_R32F"; break;
  472.     case D3DFMT_G32R32F:         pstr = L"D3DFMT_G32R32F"; break;
  473.     case D3DFMT_A32B32G32R32F:   pstr = L"D3DFMT_A32B32G32R32F"; break;
  474.     case D3DFMT_CxV8U8:          pstr = L"D3DFMT_CxV8U8"; break;
  475.     default:                     pstr = L"Unknown format"; break;
  476.     }
  477.     if( bWithPrefix || wcsstr( pstr, L"D3DFMT_" )== NULL )
  478.         return pstr;
  479.     else
  480.         return pstr + lstrlen( L"D3DFMT_" );
  481. }
  482. //--------------------------------------------------------------------------------------
  483. // Outputs to the debug stream a formatted Unicode string with a variable-argument list.
  484. //--------------------------------------------------------------------------------------
  485. VOID DXUTOutputDebugStringW( LPCWSTR strMsg, ... )
  486. {
  487. #if defined(DEBUG) || defined(_DEBUG)
  488.     WCHAR strBuffer[512];
  489.     
  490.     va_list args;
  491.     va_start(args, strMsg);
  492.     StringCchVPrintfW( strBuffer, 512, strMsg, args );
  493.     strBuffer[511] = L'';
  494.     va_end(args);
  495.     OutputDebugString( strBuffer );
  496. #else
  497.     UNREFERENCED_PARAMETER(strMsg);
  498. #endif
  499. }
  500. //--------------------------------------------------------------------------------------
  501. // Outputs to the debug stream a formatted MBCS string with a variable-argument list.
  502. //--------------------------------------------------------------------------------------
  503. VOID DXUTOutputDebugStringA( LPCSTR strMsg, ... )
  504. {
  505. #if defined(DEBUG) || defined(_DEBUG)
  506.     CHAR strBuffer[512];
  507.     
  508.     va_list args;
  509.     va_start(args, strMsg);
  510.     StringCchVPrintfA( strBuffer, 512, strMsg, args );
  511.     strBuffer[511] = '';
  512.     va_end(args);
  513.     OutputDebugStringA( strBuffer );
  514. #else
  515.     UNREFERENCED_PARAMETER(strMsg);
  516. #endif
  517. }
  518. //--------------------------------------------------------------------------------------
  519. CDXUTLineManager::CDXUTLineManager()
  520. {
  521.     m_pd3dDevice = NULL;
  522.     m_pD3DXLine = NULL;
  523. }
  524. //--------------------------------------------------------------------------------------
  525. CDXUTLineManager::~CDXUTLineManager()
  526. {
  527.     OnDeletedDevice();
  528. }
  529. //--------------------------------------------------------------------------------------
  530. HRESULT CDXUTLineManager::OnCreatedDevice( IDirect3DDevice9* pd3dDevice )
  531. {
  532.     m_pd3dDevice = pd3dDevice;
  533.     HRESULT hr;
  534.     hr = D3DXCreateLine( m_pd3dDevice, &m_pD3DXLine );
  535.     if( FAILED(hr) )
  536.         return hr;
  537.     return S_OK;
  538. }
  539. //--------------------------------------------------------------------------------------
  540. HRESULT CDXUTLineManager::OnResetDevice()
  541. {
  542.     if( m_pD3DXLine )
  543.         m_pD3DXLine->OnResetDevice();
  544.     return S_OK;
  545. }
  546. //--------------------------------------------------------------------------------------
  547. HRESULT CDXUTLineManager::OnRender()
  548. {
  549.     HRESULT hr;
  550.     if( NULL == m_pD3DXLine )
  551.         return E_INVALIDARG;
  552.     bool bDrawingHasBegun = false;
  553.     float fLastWidth = 0.0f;
  554.     bool bLastAntiAlias = false;
  555.     
  556.     for( int i=0; i<m_LinesList.GetSize(); i++ )
  557.     {
  558.         LINE_NODE* pLineNode = m_LinesList.GetAt(i);
  559.         if( pLineNode )
  560.         {
  561.             if( !bDrawingHasBegun || 
  562.                 fLastWidth != pLineNode->fWidth || 
  563.                 bLastAntiAlias != pLineNode->bAntiAlias )
  564.             {
  565.                 if( bDrawingHasBegun )
  566.                 {
  567.                     hr = m_pD3DXLine->End();
  568.                     if( FAILED(hr) )
  569.                         return hr;
  570.                 }
  571.                 m_pD3DXLine->SetWidth( pLineNode->fWidth );
  572.                 m_pD3DXLine->SetAntialias( pLineNode->bAntiAlias );
  573.                 fLastWidth = pLineNode->fWidth;
  574.                 bLastAntiAlias = pLineNode->bAntiAlias;
  575.                 hr = m_pD3DXLine->Begin();
  576.                 if( FAILED(hr) )
  577.                     return hr;
  578.                 bDrawingHasBegun = true;
  579.             }
  580.             hr = m_pD3DXLine->Draw( pLineNode->pVertexList, pLineNode->dwVertexListCount, pLineNode->Color );
  581.             if( FAILED(hr) )
  582.                 return hr;
  583.         }
  584.     }
  585.     if( bDrawingHasBegun )
  586.     {
  587.         hr = m_pD3DXLine->End();
  588.         if( FAILED(hr) )
  589.             return hr;
  590.     }
  591.     return S_OK;
  592. }
  593. //--------------------------------------------------------------------------------------
  594. HRESULT CDXUTLineManager::OnLostDevice()
  595. {
  596.     if( m_pD3DXLine )
  597.         m_pD3DXLine->OnLostDevice();
  598.     return S_OK;
  599. }
  600. //--------------------------------------------------------------------------------------
  601. HRESULT CDXUTLineManager::OnDeletedDevice()
  602. {
  603.     RemoveAllLines();
  604.     SAFE_RELEASE( m_pD3DXLine );
  605.     return S_OK;
  606. }
  607. //--------------------------------------------------------------------------------------
  608. HRESULT CDXUTLineManager::AddLine( int* pnLineID, D3DXVECTOR2* pVertexList, DWORD dwVertexListCount, D3DCOLOR Color, float fWidth, float fScaleRatio, bool bAntiAlias )
  609. {
  610.     if( pVertexList == NULL || dwVertexListCount == 0 )
  611.         return E_INVALIDARG;
  612.     LINE_NODE* pLineNode = new LINE_NODE;
  613.     if( pLineNode == NULL )
  614.         return E_OUTOFMEMORY;
  615.     ZeroMemory( pLineNode, sizeof(LINE_NODE) );
  616.     pLineNode->nLineID = m_LinesList.GetSize();
  617.     pLineNode->Color = Color;
  618.     pLineNode->fWidth = fWidth;
  619.     pLineNode->bAntiAlias = bAntiAlias;
  620.     pLineNode->dwVertexListCount = dwVertexListCount;
  621.     if( pnLineID )
  622.         *pnLineID = pLineNode->nLineID;
  623.     pLineNode->pVertexList = new D3DXVECTOR2[dwVertexListCount];
  624.     if( pLineNode->pVertexList == NULL )
  625.     {
  626.         delete pLineNode;
  627.         return E_OUTOFMEMORY;
  628.     }
  629.     for( DWORD i=0; i<dwVertexListCount; i++ )
  630.     {
  631.         pLineNode->pVertexList[i] = pVertexList[i] * fScaleRatio;
  632.     }
  633.     m_LinesList.Add( pLineNode );
  634.     return S_OK;
  635. }
  636. //--------------------------------------------------------------------------------------
  637. HRESULT CDXUTLineManager::AddRect( int* pnLineID, RECT rc, D3DCOLOR Color, float fWidth, float fScaleRatio, bool bAntiAlias )
  638. {
  639.     if( fWidth > 2.0f )
  640.     {
  641.         D3DXVECTOR2 vertexList[8];
  642.         vertexList[0].x = (float)rc.left;
  643.         vertexList[0].y = (float)rc.top - (fWidth/2.0f);
  644.         vertexList[1].x = (float)rc.left;
  645.         vertexList[1].y = (float)rc.bottom + (fWidth/2.0f);
  646.         vertexList[2].x = (float)rc.left;
  647.         vertexList[2].y = (float)rc.bottom - 0.5f;
  648.         vertexList[3].x = (float)rc.right;
  649.         vertexList[3].y = (float)rc.bottom - 0.5f;
  650.         vertexList[4].x = (float)rc.right;
  651.         vertexList[4].y = (float)rc.bottom + (fWidth/2.0f);
  652.         vertexList[5].x = (float)rc.right;
  653.         vertexList[5].y = (float)rc.top - (fWidth/2.0f);
  654.         vertexList[6].x = (float)rc.right;
  655.         vertexList[6].y = (float)rc.top;
  656.         vertexList[7].x = (float)rc.left;
  657.         vertexList[7].y = (float)rc.top;
  658.         
  659.         return AddLine( pnLineID, vertexList, 8, Color, fWidth, fScaleRatio, bAntiAlias );
  660.     }
  661.     else
  662.     {
  663.         D3DXVECTOR2 vertexList[5];
  664.         vertexList[0].x = (float)rc.left;
  665.         vertexList[0].y = (float)rc.top;
  666.         vertexList[1].x = (float)rc.left;
  667.         vertexList[1].y = (float)rc.bottom;
  668.         vertexList[2].x = (float)rc.right;
  669.         vertexList[2].y = (float)rc.bottom;
  670.         vertexList[3].x = (float)rc.right;
  671.         vertexList[3].y = (float)rc.top;
  672.         vertexList[4].x = (float)rc.left;
  673.         vertexList[4].y = (float)rc.top;
  674.         
  675.         return AddLine( pnLineID, vertexList, 5, Color, fWidth, fScaleRatio, bAntiAlias );
  676.     }
  677. }
  678. //--------------------------------------------------------------------------------------
  679. HRESULT CDXUTLineManager::RemoveLine( int nLineID )
  680. {
  681.     for( int i=0; i<m_LinesList.GetSize(); i++ )
  682.     {
  683.         LINE_NODE* pLineNode = m_LinesList.GetAt(i);
  684.         if( pLineNode && pLineNode->nLineID == nLineID )
  685.         {
  686.             SAFE_DELETE_ARRAY( pLineNode->pVertexList );
  687.             delete pLineNode;
  688.             m_LinesList.SetAt(i, NULL);
  689.         }
  690.     }
  691.     return S_OK;
  692. }
  693. //--------------------------------------------------------------------------------------
  694. HRESULT CDXUTLineManager::RemoveAllLines()
  695. {
  696.     for( int i=0; i<m_LinesList.GetSize(); i++ )
  697.     {
  698.         LINE_NODE* pLineNode = m_LinesList.GetAt(i);
  699.         if( pLineNode )
  700.         {
  701.             SAFE_DELETE_ARRAY( pLineNode->pVertexList );
  702.             delete pLineNode;
  703.         }
  704.     }
  705.     m_LinesList.RemoveAll();
  706.     return S_OK;
  707. }
  708. //--------------------------------------------------------------------------------------
  709. CDXUTTextHelper::CDXUTTextHelper( ID3DXFont* pFont, ID3DXSprite* pSprite, int nLineHeight )
  710. {
  711.     m_pFont = pFont;
  712.     m_pSprite = pSprite;
  713.     m_clr = D3DXCOLOR(1,1,1,1);
  714.     m_pt.x = 0; 
  715.     m_pt.y = 0; 
  716.     m_nLineHeight = nLineHeight;
  717. }
  718. //--------------------------------------------------------------------------------------
  719. HRESULT CDXUTTextHelper::DrawFormattedTextLine( const WCHAR* strMsg, ... )
  720. {
  721.     WCHAR strBuffer[512];
  722.     
  723.     va_list args;
  724.     va_start(args, strMsg);
  725.     StringCchVPrintf( strBuffer, 512, strMsg, args );
  726.     strBuffer[511] = L'';
  727.     va_end(args);
  728.     return DrawTextLine( strBuffer );
  729. }
  730. //--------------------------------------------------------------------------------------
  731. HRESULT CDXUTTextHelper::DrawTextLine( const WCHAR* strMsg )
  732. {
  733.     if( NULL == m_pFont ) 
  734.         return DXUT_ERR_MSGBOX( L"DrawTextLine", E_INVALIDARG );
  735.     HRESULT hr;
  736.     RECT rc;
  737.     SetRect( &rc, m_pt.x, m_pt.y, 0, 0 ); 
  738.     hr = m_pFont->DrawText( m_pSprite, strMsg, -1, &rc, DT_NOCLIP, m_clr );
  739.     if( FAILED(hr) )
  740.         return DXTRACE_ERR_MSGBOX( L"DrawText", hr );
  741.     m_pt.y += m_nLineHeight;
  742.     return S_OK;
  743. }
  744. HRESULT CDXUTTextHelper::DrawFormattedTextLine( RECT &rc, DWORD dwFlags, const WCHAR* strMsg, ... )
  745. {
  746.     WCHAR strBuffer[512];
  747.     
  748.     va_list args;
  749.     va_start(args, strMsg);
  750.     StringCchVPrintf( strBuffer, 512, strMsg, args );
  751.     strBuffer[511] = L'';
  752.     va_end(args);
  753.     return DrawTextLine( rc, dwFlags, strBuffer );
  754. }
  755. HRESULT CDXUTTextHelper::DrawTextLine( RECT &rc, DWORD dwFlags, const WCHAR* strMsg )
  756. {
  757.     if( NULL == m_pFont ) 
  758.         return DXUT_ERR_MSGBOX( L"DrawTextLine", E_INVALIDARG );
  759.     HRESULT hr;
  760.     hr = m_pFont->DrawText( m_pSprite, strMsg, -1, &rc, dwFlags, m_clr );
  761.     if( FAILED(hr) )
  762.         return DXTRACE_ERR_MSGBOX( L"DrawText", hr );
  763.     m_pt.y += m_nLineHeight;
  764.     return S_OK;
  765. }
  766. //--------------------------------------------------------------------------------------
  767. void CDXUTTextHelper::Begin()
  768. {
  769.     if( m_pSprite )
  770.         m_pSprite->Begin( D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE );
  771. }
  772. void CDXUTTextHelper::End()
  773. {
  774.     if( m_pSprite )
  775.         m_pSprite->End();
  776. }
  777. //--------------------------------------------------------------------------------------
  778. IDirect3DDevice9* CDXUTDirectionWidget::s_pd3dDevice = NULL;
  779. ID3DXEffect*      CDXUTDirectionWidget::s_pEffect = NULL;       
  780. ID3DXMesh*        CDXUTDirectionWidget::s_pMesh = NULL;    
  781. //--------------------------------------------------------------------------------------
  782. CDXUTDirectionWidget::CDXUTDirectionWidget()
  783. {
  784.     m_fRadius = 1.0f;
  785.     m_vDefaultDir = D3DXVECTOR3(0,1,0);
  786.     m_vCurrentDir = m_vDefaultDir;
  787.     m_nRotateMask = MOUSE_RIGHT_BUTTON;
  788.     D3DXMatrixIdentity( &m_mView );
  789.     D3DXMatrixIdentity( &m_mRot );
  790.     D3DXMatrixIdentity( &m_mRotSnapshot );
  791. }
  792. //--------------------------------------------------------------------------------------
  793. HRESULT CDXUTDirectionWidget::StaticOnCreateDevice( IDirect3DDevice9* pd3dDevice )
  794. {
  795.     HRESULT hr;
  796.     s_pd3dDevice = pd3dDevice;
  797.     const char* g_strBuffer = 
  798.     "float4 g_MaterialDiffuseColor;      // Material's diffuse colorrn"
  799.     "float3 g_LightDir;                  // Light's direction in world spacern"
  800.     "float4x4 g_mWorld;                  // World matrix for objectrn"
  801.     "float4x4 g_mWorldViewProjection;    // World * View * Projection matrixrn"
  802.     "rn"
  803.     "struct VS_OUTPUTrn"
  804.     "{rn"
  805.     "    float4 Position   : POSITION;   // vertex positionrn"
  806.     "    float4 Diffuse    : COLOR0;     // vertex diffuse colorrn"
  807.     "};rn"
  808.     "rn"
  809.     "VS_OUTPUT RenderWith1LightNoTextureVS( float4 vPos : POSITION,rn"
  810.     "                                       float3 vNormal : NORMAL )rn"
  811.     "{rn"
  812.     "    VS_OUTPUT Output;rn"
  813.     "rn"
  814.     "    // Transform the position from object space to homogeneous projection spacern"
  815.     "    Output.Position = mul(vPos, g_mWorldViewProjection);rn"
  816.     "rn"
  817.     "    // Transform the normal from object space to world spacern"
  818.     "    float3 vNormalWorldSpace;rn"
  819.     "    vNormalWorldSpace = normalize(mul(vNormal, (float3x3)g_mWorld)); // normal (world space)rn"
  820.     "rn"
  821.     "    // Compute simple directional lighting equationrn"
  822.     "    Output.Diffuse.rgb = g_MaterialDiffuseColor * max(0,dot(vNormalWorldSpace, g_LightDir));rn"
  823.     "    Output.Diffuse.a = 1.0f;rn"
  824.     "rn"
  825.     "    return Output;rn"
  826.     "}rn"
  827.     "rn"
  828.     "float4 RenderWith1LightNoTexturePS( float4 Diffuse : COLOR0 ) : COLOR0rn"
  829.     "{rn"
  830.     "    return Diffuse;rn"
  831.     "}rn"
  832.     "rn"
  833.     "technique RenderWith1LightNoTexturern"
  834.     "{rn"
  835.     "    pass P0rn"
  836.     "    {rn"
  837.     "        VertexShader = compile vs_1_1 RenderWith1LightNoTextureVS();rn"
  838.     "        PixelShader  = compile ps_1_1 RenderWith1LightNoTexturePS();rn"
  839.     "    }rn"
  840.     "}rn"
  841.     "";
  842.     UINT dwBufferSize = (UINT)strlen(g_strBuffer) + 1; 
  843.     V_RETURN( D3DXCreateEffect( s_pd3dDevice, g_strBuffer, dwBufferSize, NULL, NULL, D3DXFX_NOT_CLONEABLE, NULL, &s_pEffect, NULL ) );
  844.     // Load the mesh with D3DX and get back a ID3DXMesh*.  For this
  845.     // sample we'll ignore the X file's embedded materials since we know 
  846.     // exactly the model we're loading.  See the mesh samples such as
  847.     // "OptimizedMesh" for a more generic mesh loading example.
  848.     V_RETURN( DXUTCreateArrowMeshFromInternalArray( s_pd3dDevice, &s_pMesh ) );
  849.     // Optimize the mesh for this graphics card's vertex cache 
  850.     // so when rendering the mesh's triangle list the vertices will 
  851.     // cache hit more often so it won't have to re-execute the vertex shader 
  852.     // on those vertices so it will improve perf.     
  853.     DWORD* rgdwAdjacency = new DWORD[s_pMesh->GetNumFaces() * 3];
  854.     if( rgdwAdjacency == NULL )
  855.         return E_OUTOFMEMORY;
  856.     V( s_pMesh->GenerateAdjacency(1e-6f,rgdwAdjacency) );
  857.     V( s_pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL) );
  858.     delete []rgdwAdjacency;
  859.     return S_OK;
  860. }
  861. //--------------------------------------------------------------------------------------
  862. HRESULT CDXUTDirectionWidget::OnResetDevice( const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  863. {
  864.     m_ArcBall.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
  865.     return S_OK;
  866. }
  867. //--------------------------------------------------------------------------------------
  868. void CDXUTDirectionWidget::StaticOnLostDevice()
  869. {
  870.     if( s_pEffect )
  871.         s_pEffect->OnLostDevice();
  872. }
  873. //--------------------------------------------------------------------------------------
  874. void CDXUTDirectionWidget::StaticOnDestroyDevice()
  875. {
  876.     SAFE_RELEASE(s_pEffect);
  877.     SAFE_RELEASE(s_pMesh);
  878. }    
  879. //--------------------------------------------------------------------------------------
  880. LRESULT CDXUTDirectionWidget::HandleMessages( HWND hWnd, UINT uMsg, 
  881.                                               WPARAM wParam, LPARAM lParam )
  882. {
  883.     switch( uMsg )
  884.     {
  885.         case WM_LBUTTONDOWN:
  886.         case WM_MBUTTONDOWN:
  887.         case WM_RBUTTONDOWN:
  888.         {
  889.             if( ((m_nRotateMask & MOUSE_LEFT_BUTTON) != 0 && uMsg == WM_LBUTTONDOWN) ||
  890.                 ((m_nRotateMask & MOUSE_MIDDLE_BUTTON) != 0 && uMsg == WM_MBUTTONDOWN) ||
  891.                 ((m_nRotateMask & MOUSE_RIGHT_BUTTON) != 0 && uMsg == WM_RBUTTONDOWN) )
  892.             {
  893.                 int iMouseX = (int)(short)LOWORD(lParam);
  894.                 int iMouseY = (int)(short)HIWORD(lParam);
  895.                 m_ArcBall.OnBegin( iMouseX, iMouseY );
  896.                 SetCapture(hWnd);
  897.             }
  898.             return TRUE;
  899.         }
  900.         case WM_MOUSEMOVE:
  901.         {
  902.             if( m_ArcBall.IsBeingDragged() )
  903.             {
  904.                 int iMouseX = (int)(short)LOWORD(lParam);
  905.                 int iMouseY = (int)(short)HIWORD(lParam);
  906.                 m_ArcBall.OnMove( iMouseX, iMouseY );
  907.                 UpdateLightDir();
  908.             }
  909.             return TRUE;
  910.         }
  911.         case WM_LBUTTONUP:
  912.         case WM_MBUTTONUP:
  913.         case WM_RBUTTONUP:
  914.         {
  915.             if( ((m_nRotateMask & MOUSE_LEFT_BUTTON) != 0 && uMsg == WM_LBUTTONUP) ||
  916.                 ((m_nRotateMask & MOUSE_MIDDLE_BUTTON) != 0 && uMsg == WM_MBUTTONUP) ||
  917.                 ((m_nRotateMask & MOUSE_RIGHT_BUTTON) != 0 && uMsg == WM_RBUTTONUP) )
  918.             {
  919.                 m_ArcBall.OnEnd();
  920.                 ReleaseCapture();
  921.             }
  922.             UpdateLightDir();
  923.             return TRUE;
  924.         }
  925.         case WM_CAPTURECHANGED:
  926.         {
  927.             if( (HWND)lParam != hWnd )
  928.             {
  929.                 if( (m_nRotateMask & MOUSE_LEFT_BUTTON) ||
  930.                     (m_nRotateMask & MOUSE_MIDDLE_BUTTON) ||
  931.                     (m_nRotateMask & MOUSE_RIGHT_BUTTON) )
  932.                 {
  933.                     m_ArcBall.OnEnd();
  934.                     ReleaseCapture();
  935.                 }
  936.             }
  937.             return TRUE;
  938.         }
  939.     }
  940.     return 0;
  941. }
  942. //--------------------------------------------------------------------------------------
  943. HRESULT CDXUTDirectionWidget::OnRender( D3DXCOLOR color, const D3DXMATRIX* pmView, 
  944.                                         const D3DXMATRIX* pmProj, const D3DXVECTOR3* pEyePt )
  945. {
  946.     m_mView = *pmView;
  947.     // Render the light spheres so the user can visually see the light dir
  948.     UINT iPass, cPasses;
  949.     D3DXMATRIX mRotate;
  950.     D3DXMATRIX mScale;
  951.     D3DXMATRIX mTrans;
  952.     D3DXMATRIXA16 mWorldViewProj;
  953.     HRESULT hr;
  954.     V( s_pEffect->SetTechnique( "RenderWith1LightNoTexture" ) );
  955.     V( s_pEffect->SetVector( "g_MaterialDiffuseColor", (D3DXVECTOR4*)&color ) );
  956.     D3DXVECTOR3 vEyePt;
  957.     D3DXVec3Normalize( &vEyePt, pEyePt );
  958.     V( s_pEffect->SetValue( "g_LightDir", &vEyePt, sizeof(D3DXVECTOR3) ) );
  959.     // Rotate arrow model to point towards origin
  960.     D3DXMATRIX mRotateA, mRotateB;
  961.     D3DXVECTOR3 vAt = D3DXVECTOR3(0,0,0);
  962.     D3DXVECTOR3 vUp = D3DXVECTOR3(0,1,0);
  963.     D3DXMatrixRotationX( &mRotateB, D3DX_PI );
  964.     D3DXMatrixLookAtLH( &mRotateA, &m_vCurrentDir, &vAt, &vUp );
  965.     D3DXMatrixInverse( &mRotateA, NULL, &mRotateA );
  966.     mRotate = mRotateB * mRotateA;
  967.     D3DXVECTOR3 vL = m_vCurrentDir * m_fRadius * 1.0f;
  968.     D3DXMatrixTranslation( &mTrans, vL.x, vL.y, vL.z );
  969.     D3DXMatrixScaling( &mScale, m_fRadius*0.2f, m_fRadius*0.2f, m_fRadius*0.2f );
  970.     D3DXMATRIX mWorld = mRotate * mScale * mTrans;
  971.     mWorldViewProj = mWorld * (m_mView) * (*pmProj);
  972.     V( s_pEffect->SetMatrix( "g_mWorldViewProjection", &mWorldViewProj ) );
  973.     V( s_pEffect->SetMatrix( "g_mWorld", &mWorld ) );
  974.     for( int iSubset=0; iSubset<2; iSubset++ )
  975.     {
  976.         V( s_pEffect->Begin(&cPasses, 0) );
  977.         for (iPass = 0; iPass < cPasses; iPass++)
  978.         {
  979.             V( s_pEffect->BeginPass(iPass) );
  980.             V( s_pMesh->DrawSubset(iSubset) );
  981.             V( s_pEffect->EndPass() );
  982.         }
  983.         V( s_pEffect->End() );
  984.     }
  985.     return S_OK;
  986. }
  987. //--------------------------------------------------------------------------------------
  988. HRESULT CDXUTDirectionWidget::UpdateLightDir()
  989. {
  990.     D3DXMATRIX mInvView;
  991.     D3DXMatrixInverse(&mInvView, NULL, &m_mView);
  992.     mInvView._41 = mInvView._42 = mInvView._43 = 0;
  993.     D3DXMATRIX mLastRotInv;
  994.     D3DXMatrixInverse(&mLastRotInv, NULL, &m_mRotSnapshot);
  995.     D3DXMATRIX mRot = *m_ArcBall.GetRotationMatrix();
  996.     m_mRotSnapshot = mRot;
  997.     // Accumulate the delta of the arcball's rotation in view space.
  998.     // Note that per-frame delta rotations could be problematic over long periods of time.
  999.     m_mRot *= m_mView * mLastRotInv * mRot * mInvView;
  1000.     // Since we're accumulating delta rotations, we need to orthonormalize 
  1001.     // the matrix to prevent eventual matrix skew
  1002.     D3DXVECTOR3* pXBasis = (D3DXVECTOR3*) &m_mRot._11;
  1003.     D3DXVECTOR3* pYBasis = (D3DXVECTOR3*) &m_mRot._21;
  1004.     D3DXVECTOR3* pZBasis = (D3DXVECTOR3*) &m_mRot._31;
  1005.     D3DXVec3Normalize( pXBasis, pXBasis );
  1006.     D3DXVec3Cross( pYBasis, pZBasis, pXBasis );
  1007.     D3DXVec3Normalize( pYBasis, pYBasis );
  1008.     D3DXVec3Cross( pZBasis, pXBasis, pYBasis );
  1009.     // Transform the default direction vector by the light's rotation matrix
  1010.     D3DXVec3TransformNormal( &m_vCurrentDir, &m_vDefaultDir, &m_mRot );
  1011.     return S_OK;
  1012. }
  1013. //--------------------------------------------------------------------------------------
  1014. // Direct3D9 dynamic linking support -- calls top-level D3D9 APIs with graceful
  1015. // failure if APIs are not present.
  1016. //--------------------------------------------------------------------------------------
  1017. // Function prototypes
  1018. typedef IDirect3D9* (WINAPI * LPDIRECT3DCREATE9) (UINT);
  1019. typedef INT         (WINAPI * LPD3DPERF_BEGINEVENT)(D3DCOLOR, LPCWSTR);
  1020. typedef INT         (WINAPI * LPD3DPERF_ENDEVENT)(void);
  1021. typedef VOID        (WINAPI * LPD3DPERF_SETMARKER)(D3DCOLOR, LPCWSTR);
  1022. typedef VOID        (WINAPI * LPD3DPERF_SETREGION)(D3DCOLOR, LPCWSTR);
  1023. typedef BOOL        (WINAPI * LPD3DPERF_QUERYREPEATFRAME)(void);
  1024. typedef VOID        (WINAPI * LPD3DPERF_SETOPTIONS)( DWORD dwOptions );
  1025. typedef DWORD       (WINAPI * LPD3DPERF_GETSTATUS)( void );
  1026. // Module and function pointers
  1027. static HMODULE s_hModD3D9 = NULL;
  1028. static LPDIRECT3DCREATE9 s_DynamicDirect3DCreate9 = NULL;
  1029. static LPD3DPERF_BEGINEVENT s_DynamicD3DPERF_BeginEvent = NULL;
  1030. static LPD3DPERF_ENDEVENT s_DynamicD3DPERF_EndEvent = NULL;
  1031. static LPD3DPERF_SETMARKER s_DynamicD3DPERF_SetMarker = NULL;
  1032. static LPD3DPERF_SETREGION s_DynamicD3DPERF_SetRegion = NULL;
  1033. static LPD3DPERF_QUERYREPEATFRAME s_DynamicD3DPERF_QueryRepeatFrame = NULL;
  1034. static LPD3DPERF_SETOPTIONS s_DynamicD3DPERF_SetOptions = NULL;
  1035. static LPD3DPERF_GETSTATUS s_DynamicD3DPERF_GetStatus = NULL;
  1036. // Ensure function pointers are initialized
  1037. static bool DXUT_EnsureD3DAPIs( void )
  1038. {
  1039.     // If module is non-NULL, this function has already been called.  Note
  1040.     // that this doesn't guarantee that all D3D9 procaddresses were found.
  1041.     if( s_hModD3D9 != NULL )
  1042.         return true;
  1043.     // This may fail if DirectX 9 isn't installed
  1044.     WCHAR wszPath[MAX_PATH+1];
  1045.     if( !::GetSystemDirectory( wszPath, MAX_PATH+1 ) )
  1046.         return false;
  1047.     StringCchCat( wszPath, MAX_PATH, L"\d3d9.dll" );
  1048.     s_hModD3D9 = LoadLibrary( wszPath );
  1049.     if( s_hModD3D9 == NULL ) 
  1050.         return false;
  1051.     s_DynamicDirect3DCreate9 = (LPDIRECT3DCREATE9)GetProcAddress( s_hModD3D9, "Direct3DCreate9" );
  1052.     s_DynamicD3DPERF_BeginEvent = (LPD3DPERF_BEGINEVENT)GetProcAddress( s_hModD3D9, "D3DPERF_BeginEvent" );
  1053.     s_DynamicD3DPERF_EndEvent = (LPD3DPERF_ENDEVENT)GetProcAddress( s_hModD3D9, "D3DPERF_EndEvent" );
  1054.     s_DynamicD3DPERF_SetMarker = (LPD3DPERF_SETMARKER)GetProcAddress( s_hModD3D9, "D3DPERF_SetMarker" );
  1055.     s_DynamicD3DPERF_SetRegion = (LPD3DPERF_SETREGION)GetProcAddress( s_hModD3D9, "D3DPERF_SetRegion" );
  1056.     s_DynamicD3DPERF_QueryRepeatFrame = (LPD3DPERF_QUERYREPEATFRAME)GetProcAddress( s_hModD3D9, "D3DPERF_QueryRepeatFrame" );
  1057.     s_DynamicD3DPERF_SetOptions = (LPD3DPERF_SETOPTIONS)GetProcAddress( s_hModD3D9, "D3DPERF_SetOptions" );
  1058.     s_DynamicD3DPERF_GetStatus = (LPD3DPERF_GETSTATUS)GetProcAddress( s_hModD3D9, "D3DPERF_GetStatus" );
  1059.     return true;
  1060. }
  1061. IDirect3D9 * WINAPI DXUT_Dynamic_Direct3DCreate9(UINT SDKVersion) 
  1062. {
  1063.     if( DXUT_EnsureD3DAPIs() && s_DynamicDirect3DCreate9 != NULL )
  1064.         return s_DynamicDirect3DCreate9( SDKVersion );
  1065.     else
  1066.         return NULL;
  1067. }
  1068. int WINAPI DXUT_Dynamic_D3DPERF_BeginEvent( D3DCOLOR col, LPCWSTR wszName )
  1069. {
  1070.     if( DXUT_EnsureD3DAPIs() && s_DynamicD3DPERF_BeginEvent != NULL )
  1071.         return s_DynamicD3DPERF_BeginEvent( col, wszName );
  1072.     else
  1073.         return -1;
  1074. }
  1075. int WINAPI DXUT_Dynamic_D3DPERF_EndEvent( void )
  1076. {
  1077.     if( DXUT_EnsureD3DAPIs() && s_DynamicD3DPERF_EndEvent != NULL )
  1078.         return s_DynamicD3DPERF_EndEvent();
  1079.     else
  1080.         return -1;
  1081. }
  1082. void WINAPI DXUT_Dynamic_D3DPERF_SetMarker( D3DCOLOR col, LPCWSTR wszName )
  1083. {
  1084.     if( DXUT_EnsureD3DAPIs() && s_DynamicD3DPERF_SetMarker != NULL )
  1085.         s_DynamicD3DPERF_SetMarker( col, wszName );
  1086. }
  1087. void WINAPI DXUT_Dynamic_D3DPERF_SetRegion( D3DCOLOR col, LPCWSTR wszName )
  1088. {
  1089.     if( DXUT_EnsureD3DAPIs() && s_DynamicD3DPERF_SetRegion != NULL )
  1090.         s_DynamicD3DPERF_SetRegion( col, wszName );
  1091. }
  1092. BOOL WINAPI DXUT_Dynamic_D3DPERF_QueryRepeatFrame( void )
  1093. {
  1094.     if( DXUT_EnsureD3DAPIs() && s_DynamicD3DPERF_QueryRepeatFrame != NULL )
  1095.         return s_DynamicD3DPERF_QueryRepeatFrame();
  1096.     else
  1097.         return FALSE;
  1098. }
  1099. void WINAPI DXUT_Dynamic_D3DPERF_SetOptions( DWORD dwOptions )
  1100. {
  1101.     if( DXUT_EnsureD3DAPIs() && s_DynamicD3DPERF_SetOptions != NULL )
  1102.         s_DynamicD3DPERF_SetOptions( dwOptions );
  1103. }
  1104. DWORD WINAPI DXUT_Dynamic_D3DPERF_GetStatus( void )
  1105. {
  1106.     if( DXUT_EnsureD3DAPIs() && s_DynamicD3DPERF_GetStatus != NULL )
  1107.         return s_DynamicD3DPERF_GetStatus();
  1108.     else
  1109.         return 0;
  1110. }
  1111. //--------------------------------------------------------------------------------------
  1112. // Trace a string description of a decl 
  1113. //--------------------------------------------------------------------------------------
  1114. void DXUTTraceDecl( D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE] )
  1115. {
  1116.     int iDecl=0;
  1117.     for( iDecl=0; iDecl<MAX_FVF_DECL_SIZE; iDecl++ )
  1118.     {
  1119.         if( decl[iDecl].Stream == 0xFF )
  1120.             break;
  1121.         DXUTOutputDebugString( L"decl[%d]=Stream:%d, Offset:%d, %s, %s, %s, UsageIndex:%dn", iDecl, 
  1122.                     decl[iDecl].Stream,
  1123.                     decl[iDecl].Offset,
  1124.                     DXUTTraceD3DDECLTYPEtoString( decl[iDecl].Type ),
  1125.                     DXUTTraceD3DDECLMETHODtoString( decl[iDecl].Method ),
  1126.                     DXUTTraceD3DDECLUSAGEtoString( decl[iDecl].Usage ),
  1127.                     decl[iDecl].UsageIndex );
  1128.     }
  1129.     DXUTOutputDebugString( L"decl[%d]=D3DDECL_ENDn", iDecl );
  1130. }
  1131. //--------------------------------------------------------------------------------------
  1132. WCHAR* DXUTTraceD3DDECLTYPEtoString( BYTE t )
  1133. {
  1134.     switch( t )
  1135.     {
  1136.         case D3DDECLTYPE_FLOAT1: return L"D3DDECLTYPE_FLOAT1";
  1137.         case D3DDECLTYPE_FLOAT2: return L"D3DDECLTYPE_FLOAT2";
  1138.         case D3DDECLTYPE_FLOAT3: return L"D3DDECLTYPE_FLOAT3";
  1139.         case D3DDECLTYPE_FLOAT4: return L"D3DDECLTYPE_FLOAT4";
  1140.         case D3DDECLTYPE_D3DCOLOR: return L"D3DDECLTYPE_D3DCOLOR";
  1141.         case D3DDECLTYPE_UBYTE4: return L"D3DDECLTYPE_UBYTE4";
  1142.         case D3DDECLTYPE_SHORT2: return L"D3DDECLTYPE_SHORT2";
  1143.         case D3DDECLTYPE_SHORT4: return L"D3DDECLTYPE_SHORT4";
  1144.         case D3DDECLTYPE_UBYTE4N: return L"D3DDECLTYPE_UBYTE4N";
  1145.         case D3DDECLTYPE_SHORT2N: return L"D3DDECLTYPE_SHORT2N";
  1146.         case D3DDECLTYPE_SHORT4N: return L"D3DDECLTYPE_SHORT4N";
  1147.         case D3DDECLTYPE_USHORT2N: return L"D3DDECLTYPE_USHORT2N";
  1148.         case D3DDECLTYPE_USHORT4N: return L"D3DDECLTYPE_USHORT4N";
  1149.         case D3DDECLTYPE_UDEC3: return L"D3DDECLTYPE_UDEC3";
  1150.         case D3DDECLTYPE_DEC3N: return L"D3DDECLTYPE_DEC3N";
  1151.         case D3DDECLTYPE_FLOAT16_2: return L"D3DDECLTYPE_FLOAT16_2";
  1152.         case D3DDECLTYPE_FLOAT16_4: return L"D3DDECLTYPE_FLOAT16_4";
  1153.         case D3DDECLTYPE_UNUSED: return L"D3DDECLTYPE_UNUSED";
  1154.         default: return L"D3DDECLTYPE Unknown";
  1155.     }
  1156. }
  1157. WCHAR* DXUTTraceD3DDECLMETHODtoString( BYTE m )
  1158. {
  1159.     switch( m )
  1160.     {
  1161.         case D3DDECLMETHOD_DEFAULT: return L"D3DDECLMETHOD_DEFAULT";
  1162.         case D3DDECLMETHOD_PARTIALU: return L"D3DDECLMETHOD_PARTIALU";
  1163.         case D3DDECLMETHOD_PARTIALV: return L"D3DDECLMETHOD_PARTIALV";
  1164.         case D3DDECLMETHOD_CROSSUV: return L"D3DDECLMETHOD_CROSSUV";
  1165.         case D3DDECLMETHOD_UV: return L"D3DDECLMETHOD_UV";
  1166.         case D3DDECLMETHOD_LOOKUP: return L"D3DDECLMETHOD_LOOKUP";
  1167.         case D3DDECLMETHOD_LOOKUPPRESAMPLED: return L"D3DDECLMETHOD_LOOKUPPRESAMPLED";
  1168.         default: return L"D3DDECLMETHOD Unknown";
  1169.     }
  1170. }
  1171. WCHAR* DXUTTraceD3DDECLUSAGEtoString( BYTE u )
  1172. {
  1173.     switch( u )
  1174.     {
  1175.         case D3DDECLUSAGE_POSITION: return L"D3DDECLUSAGE_POSITION";
  1176.         case D3DDECLUSAGE_BLENDWEIGHT: return L"D3DDECLUSAGE_BLENDWEIGHT";
  1177.         case D3DDECLUSAGE_BLENDINDICES: return L"D3DDECLUSAGE_BLENDINDICES";
  1178.         case D3DDECLUSAGE_NORMAL: return L"D3DDECLUSAGE_NORMAL";
  1179.         case D3DDECLUSAGE_PSIZE: return L"D3DDECLUSAGE_PSIZE";
  1180.         case D3DDECLUSAGE_TEXCOORD: return L"D3DDECLUSAGE_TEXCOORD";
  1181.         case D3DDECLUSAGE_TANGENT: return L"D3DDECLUSAGE_TANGENT";
  1182.         case D3DDECLUSAGE_BINORMAL: return L"D3DDECLUSAGE_BINORMAL";
  1183.         case D3DDECLUSAGE_TESSFACTOR: return L"D3DDECLUSAGE_TESSFACTOR";
  1184.         case D3DDECLUSAGE_POSITIONT: return L"D3DDECLUSAGE_POSITIONT";
  1185.         case D3DDECLUSAGE_COLOR: return L"D3DDECLUSAGE_COLOR";
  1186.         case D3DDECLUSAGE_FOG: return L"D3DDECLUSAGE_FOG";
  1187.         case D3DDECLUSAGE_DEPTH: return L"D3DDECLUSAGE_DEPTH";
  1188.         case D3DDECLUSAGE_SAMPLE: return L"D3DDECLUSAGE_SAMPLE";
  1189.         default: return L"D3DDECLUSAGE Unknown";
  1190.     }
  1191. }
  1192. //--------------------------------------------------------------------------------------
  1193. // Multimon API handling for OSes with or without multimon API support
  1194. //--------------------------------------------------------------------------------------
  1195. #define DXUT_PRIMARY_MONITOR ((HMONITOR)0x12340042)
  1196. typedef HMONITOR (WINAPI* LPMONITORFROMWINDOW)(HWND, DWORD);
  1197. typedef BOOL     (WINAPI* LPGETMONITORINFO)(HMONITOR, LPMONITORINFO);
  1198. BOOL DXUTGetMonitorInfo(HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo)
  1199. {
  1200.     static bool s_bInited = false;
  1201.     static LPGETMONITORINFO s_pFnGetMonitorInfo = NULL;
  1202.     if( !s_bInited )        
  1203.     {
  1204.         s_bInited = true;
  1205.         HMODULE hUser32 = GetModuleHandle( L"USER32" );
  1206.         if (hUser32 ) 
  1207.         {
  1208.             OSVERSIONINFOA osvi = {0}; osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionExA((OSVERSIONINFOA*)&osvi);
  1209.             bool bNT = (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId);    
  1210.             s_pFnGetMonitorInfo = (LPGETMONITORINFO) (bNT ? GetProcAddress(hUser32,"GetMonitorInfoW") : GetProcAddress(hUser32,"GetMonitorInfoA"));
  1211.         }
  1212.     }
  1213.     if( s_pFnGetMonitorInfo ) 
  1214.         return s_pFnGetMonitorInfo(hMonitor, lpMonitorInfo);
  1215.     RECT rcWork;
  1216.     if ((hMonitor == DXUT_PRIMARY_MONITOR) && lpMonitorInfo && (lpMonitorInfo->cbSize >= sizeof(MONITORINFO)) && SystemParametersInfoA(SPI_GETWORKAREA, 0, &rcWork, 0))
  1217.     {
  1218.         lpMonitorInfo->rcMonitor.left = 0;
  1219.         lpMonitorInfo->rcMonitor.top  = 0;
  1220.         lpMonitorInfo->rcMonitor.right  = GetSystemMetrics(SM_CXSCREEN);
  1221.         lpMonitorInfo->rcMonitor.bottom = GetSystemMetrics(SM_CYSCREEN);
  1222.         lpMonitorInfo->rcWork = rcWork;
  1223.         lpMonitorInfo->dwFlags = MONITORINFOF_PRIMARY;
  1224.         return TRUE;
  1225.     }
  1226.     return FALSE;
  1227. }
  1228. HMONITOR DXUTMonitorFromWindow(HWND hWnd, DWORD dwFlags)
  1229. {
  1230.     static bool s_bInited = false;
  1231.     static LPMONITORFROMWINDOW s_pFnGetMonitorFronWindow = NULL;
  1232.     if( !s_bInited )        
  1233.     {
  1234.         s_bInited = true;
  1235.         HMODULE hUser32 = GetModuleHandle( L"USER32" );
  1236.         if (hUser32 ) s_pFnGetMonitorFronWindow = (LPMONITORFROMWINDOW) GetProcAddress(hUser32,"MonitorFromWindow");
  1237.     }
  1238.     if( s_pFnGetMonitorFronWindow ) 
  1239.         return s_pFnGetMonitorFronWindow(hWnd, dwFlags);
  1240.     if (dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST))
  1241.         return DXUT_PRIMARY_MONITOR;
  1242.     return NULL;
  1243. }
  1244. //--------------------------------------------------------------------------------------
  1245. // Get the desktop resolution of an adapter. This isn't the same as the current resolution 
  1246. // from GetAdapterDisplayMode since the device might be fullscreen 
  1247. //--------------------------------------------------------------------------------------
  1248. void DXUTGetDesktopResolution( UINT AdapterOrdinal, UINT* pWidth, UINT* pHeight )
  1249. {
  1250.     CD3DEnumeration* pd3dEnum = DXUTGetEnumeration();
  1251.     CD3DEnumAdapterInfo* pAdapterInfo = pd3dEnum->GetAdapterInfo( AdapterOrdinal );                       
  1252.     DEVMODE devMode;
  1253.     ZeroMemory( &devMode, sizeof(DEVMODE) );
  1254.     devMode.dmSize = sizeof(DEVMODE);
  1255.     WCHAR strDeviceName[256];
  1256.     MultiByteToWideChar( CP_ACP, 0, pAdapterInfo->AdapterIdentifier.DeviceName, -1, strDeviceName, 256 );
  1257.     strDeviceName[255] = 0;
  1258.     EnumDisplaySettings( strDeviceName, ENUM_REGISTRY_SETTINGS, &devMode );
  1259.     
  1260.     if( pWidth )
  1261.         *pWidth = devMode.dmPelsWidth;
  1262.     if( pHeight )
  1263.         *pHeight = devMode.dmPelsHeight;
  1264. }
  1265. //--------------------------------------------------------------------------------------
  1266. IDirect3DDevice9* DXUTCreateRefDevice( HWND hWnd, bool bNullRef )
  1267. {
  1268.     HRESULT hr;
  1269.     IDirect3D9* pD3D = DXUT_Dynamic_Direct3DCreate9( D3D_SDK_VERSION );
  1270.     if( NULL == pD3D )
  1271.         return NULL;
  1272.     D3DDISPLAYMODE Mode;
  1273.     pD3D->GetAdapterDisplayMode(0, &Mode);
  1274.     D3DPRESENT_PARAMETERS pp;
  1275.     ZeroMemory( &pp, sizeof(D3DPRESENT_PARAMETERS) );
  1276.     pp.BackBufferWidth  = 1;
  1277.     pp.BackBufferHeight = 1;
  1278.     pp.BackBufferFormat = Mode.Format;
  1279.     pp.BackBufferCount  = 1;
  1280.     pp.SwapEffect       = D3DSWAPEFFECT_COPY;
  1281.     pp.Windowed         = TRUE;
  1282.     pp.hDeviceWindow    = hWnd;
  1283.     IDirect3DDevice9* pd3dDevice = NULL;
  1284.     hr = pD3D->CreateDevice( D3DADAPTER_DEFAULT, bNullRef ? D3DDEVTYPE_NULLREF : D3DDEVTYPE_REF,
  1285.                              hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, &pd3dDevice );
  1286.     SAFE_RELEASE( pD3D );
  1287.     return pd3dDevice;
  1288. }
  1289. typedef DWORD (WINAPI* LPXINPUTGETSTATE)(DWORD dwUserIndex, XINPUT_STATE* pState );
  1290. typedef DWORD (WINAPI* LPXINPUTSETSTATE)(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration );
  1291. typedef DWORD (WINAPI* LPXINPUTGETCAPABILITIES)( DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities );
  1292. //--------------------------------------------------------------------------------------
  1293. // Does extra processing on XInput data to make it slightly more convenient to use
  1294. //--------------------------------------------------------------------------------------
  1295. HRESULT DXUTGetGamepadState( DWORD dwPort, DXUT_GAMEPAD* pGamePad, bool bThumbstickDeadZone, bool bSnapThumbstickToCardinals )
  1296. {
  1297.     if( dwPort >= DXUT_MAX_CONTROLLERS || pGamePad == NULL )
  1298.         return E_FAIL;
  1299.     static LPXINPUTGETSTATE s_pXInputGetState = NULL;
  1300.     static LPXINPUTGETCAPABILITIES s_pXInputGetCapabilities = NULL;
  1301.     if( NULL == s_pXInputGetState || NULL == s_pXInputGetCapabilities )
  1302.     {
  1303.         WCHAR wszPath[MAX_PATH];
  1304.         if( GetSystemDirectory( wszPath, MAX_PATH ) )
  1305.         {
  1306.             StringCchCat( wszPath, MAX_PATH, L"\" );
  1307.             StringCchCat( wszPath, MAX_PATH, XINPUT_DLL );
  1308.             HINSTANCE hInst = LoadLibrary( wszPath );
  1309.             if( hInst ) 
  1310.             {
  1311.                 s_pXInputGetState = (LPXINPUTGETSTATE)GetProcAddress( hInst, "XInputGetState" );
  1312.                 s_pXInputGetCapabilities = (LPXINPUTGETCAPABILITIES)GetProcAddress( hInst, "XInputGetCapabilities" );
  1313.             }
  1314.         }
  1315.     }
  1316.     if( s_pXInputGetState == NULL )
  1317.         return E_FAIL;
  1318.     XINPUT_STATE InputState;
  1319.     DWORD dwResult = s_pXInputGetState( dwPort, &InputState );
  1320.     // Track insertion and removals
  1321.     BOOL bWasConnected = pGamePad->bConnected;
  1322.     pGamePad->bConnected = (dwResult == ERROR_SUCCESS);
  1323.     pGamePad->bRemoved  = (  bWasConnected && !pGamePad->bConnected );
  1324.     pGamePad->bInserted = ( !bWasConnected &&  pGamePad->bConnected );
  1325.     // Don't update rest of the state if not connected
  1326.     if( !pGamePad->bConnected )
  1327.         return S_OK;
  1328.     // Store the capabilities of the device
  1329.     if( pGamePad->bInserted )
  1330.     {
  1331.         ZeroMemory( pGamePad, sizeof(DXUT_GAMEPAD) );
  1332.         pGamePad->bConnected = true;
  1333.         pGamePad->bInserted  = true;
  1334.         if( s_pXInputGetCapabilities )
  1335.             s_pXInputGetCapabilities( dwPort, XINPUT_DEVTYPE_GAMEPAD, &pGamePad->caps );
  1336.     }
  1337.     // Copy gamepad to local structure (assumes that XINPUT_GAMEPAD at the front in CONTROLER_STATE)
  1338.     memcpy( pGamePad, &InputState.Gamepad, sizeof(XINPUT_GAMEPAD) );
  1339.     if( bSnapThumbstickToCardinals )
  1340.     {
  1341.         // Apply deadzone to each axis independantly to slightly snap to up/down/left/right
  1342.         if( pGamePad->sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && pGamePad->sThumbLX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE )
  1343.             pGamePad->sThumbLX = 0;
  1344.         if( pGamePad->sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && pGamePad->sThumbLY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ) 
  1345.             pGamePad->sThumbLY = 0;
  1346.         if( pGamePad->sThumbRX < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE && pGamePad->sThumbRX > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE )
  1347.             pGamePad->sThumbRX = 0;
  1348.         if( pGamePad->sThumbRY < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE && pGamePad->sThumbRY > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ) 
  1349.             pGamePad->sThumbRY = 0;
  1350.     }
  1351.     else if( bThumbstickDeadZone )
  1352.     {
  1353.         // Apply deadzone if centered
  1354.         if( (pGamePad->sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && pGamePad->sThumbLX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) && 
  1355.             (pGamePad->sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && pGamePad->sThumbLY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) ) 
  1356.         {   
  1357.             pGamePad->sThumbLX = 0;
  1358.             pGamePad->sThumbLY = 0;
  1359.         }
  1360.         if( (pGamePad->sThumbRX < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE && pGamePad->sThumbRX > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) && 
  1361.             (pGamePad->sThumbRY < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE && pGamePad->sThumbRY > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) ) 
  1362.         {
  1363.             pGamePad->sThumbRX = 0;
  1364.             pGamePad->sThumbRY = 0;
  1365.         }
  1366.     }
  1367.     // Convert [-1,+1] range
  1368.     pGamePad->fThumbLX = pGamePad->sThumbLX / 32767.0f;
  1369.     pGamePad->fThumbLY = pGamePad->sThumbLY / 32767.0f;
  1370.     pGamePad->fThumbRX = pGamePad->sThumbRX / 32767.0f;
  1371.     pGamePad->fThumbRY = pGamePad->sThumbRY / 32767.0f;
  1372.     // Get the boolean buttons that have been pressed since the last call. 
  1373.     // Each button is represented by one bit.
  1374.     pGamePad->wPressedButtons = ( pGamePad->wLastButtons ^ pGamePad->wButtons ) & pGamePad->wButtons;
  1375.     pGamePad->wLastButtons    = pGamePad->wButtons;
  1376.     // Figure out if the left trigger has been pressed or released
  1377.     bool bPressed = ( pGamePad->bLeftTrigger > DXUT_GAMEPAD_TRIGGER_THRESHOLD );
  1378.     pGamePad->bPressedLeftTrigger = ( bPressed ) ? !pGamePad->bLastLeftTrigger : false;
  1379.     pGamePad->bLastLeftTrigger = bPressed;
  1380.     // Figure out if the right trigger has been pressed or released
  1381.     bPressed = ( pGamePad->bRightTrigger > DXUT_GAMEPAD_TRIGGER_THRESHOLD );
  1382.     pGamePad->bPressedRightTrigger = ( bPressed ) ? !pGamePad->bLastRightTrigger : false;
  1383.     pGamePad->bLastRightTrigger = bPressed;
  1384.     return S_OK;
  1385. }
  1386. //--------------------------------------------------------------------------------------
  1387. // Don't pause the game or deactive the window without first stopping rumble otherwise 
  1388. // the controller will continue to rumble
  1389. //--------------------------------------------------------------------------------------
  1390. HRESULT DXUTStopRumbleOnAllControllers()
  1391. {
  1392.     static LPXINPUTSETSTATE s_pXInputSetState = NULL;
  1393.     if( NULL == s_pXInputSetState )
  1394.     {
  1395.         WCHAR wszPath[MAX_PATH];
  1396.         if( GetSystemDirectory( wszPath, MAX_PATH ) )
  1397.         {
  1398.             StringCchCat( wszPath, MAX_PATH, L"\" );
  1399.             StringCchCat( wszPath, MAX_PATH, XINPUT_DLL );
  1400.             HINSTANCE hInst = LoadLibrary( wszPath );
  1401.             if( hInst ) 
  1402.                 s_pXInputSetState = (LPXINPUTSETSTATE)GetProcAddress( hInst, "XInputSetState" );
  1403.         }
  1404.     }
  1405.     if( s_pXInputSetState == NULL )
  1406.         return E_FAIL;
  1407.     XINPUT_VIBRATION vibration;
  1408.     vibration.wLeftMotorSpeed  = 0;
  1409.     vibration.wRightMotorSpeed = 0;
  1410.     for( int iUserIndex=0; iUserIndex<DXUT_MAX_CONTROLLERS; iUserIndex++ )
  1411.         s_pXInputSetState( iUserIndex, &vibration );
  1412.     return S_OK;
  1413. }
  1414. //--------------------------------------------------------------------------------------
  1415. // Helper function to launch the Media Center UI after the program terminates
  1416. //--------------------------------------------------------------------------------------
  1417. bool DXUTReLaunchMediaCenter()
  1418. {
  1419.     // Skip if not running on a Media Center
  1420.     if( GetSystemMetrics( 87 ) == 0 ) //  SM_MEDIACENTER == 87, but is only defined if _WIN32_WINNT >= 0x0501
  1421.         return false;
  1422.  
  1423.     // Get the path to Media Center
  1424.     WCHAR szExpandedPath[MAX_PATH];
  1425.     if( !ExpandEnvironmentStrings( L"%SystemRoot%\ehome\ehshell.exe", szExpandedPath, MAX_PATH) )
  1426.         return false;
  1427.     // Skip if ehshell.exe doesn't exist
  1428.     if( GetFileAttributes( szExpandedPath ) == 0xFFFFFFFF )
  1429.         return false;
  1430.  
  1431.     // Launch ehshell.exe 
  1432.     INT_PTR result = (INT_PTR)ShellExecute( NULL, TEXT("open"), szExpandedPath, NULL, NULL, SW_SHOWNORMAL);
  1433.     return (result > 32);
  1434. }