d3dutil.cpp
上传用户:fengshi120
上传日期:2014-07-17
资源大小:6155k
文件大小:25k
源码类别:

3D图形编程

开发平台:

C/C++

  1. //-----------------------------------------------------------------------------
  2. // File: D3DUtil.cpp
  3. //
  4. // Desc: Shortcut macros and functions for using DX objects
  5. //-----------------------------------------------------------------------------
  6. #define STRICT
  7. #include "stdafx.h"
  8. #include <Windows.h>
  9. #include <WindowsX.h>
  10. #include <tchar.h>
  11. #include <stdio.h>
  12. #include "D3DUtil.h"
  13. #include "DXUtil.h"
  14. #include "D3DX9.h"
  15. //-----------------------------------------------------------------------------
  16. // Name: D3DUtil_InitMaterial()
  17. // Desc: Initializes a D3DMATERIAL9 structure, setting the diffuse and ambient
  18. //       colors. It does not set emissive or specular colors.
  19. //-----------------------------------------------------------------------------
  20. VOID D3DUtil_InitMaterial( D3DMATERIAL9& mtrl, FLOAT r, FLOAT g, FLOAT b,
  21.                            FLOAT a )
  22. {
  23.     ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );
  24.     mtrl.Diffuse.r = mtrl.Ambient.r = r;
  25.     mtrl.Diffuse.g = mtrl.Ambient.g = g;
  26.     mtrl.Diffuse.b = mtrl.Ambient.b = b;
  27.     mtrl.Diffuse.a = mtrl.Ambient.a = a;
  28. }
  29. //-----------------------------------------------------------------------------
  30. // Name: D3DUtil_InitLight()
  31. // Desc: Initializes a D3DLIGHT structure, setting the light position. The
  32. //       diffuse color is set to white; specular and ambient are left as black.
  33. //-----------------------------------------------------------------------------
  34. VOID D3DUtil_InitLight( D3DLIGHT9& light, D3DLIGHTTYPE ltType,
  35.                         FLOAT x, FLOAT y, FLOAT z )
  36. {
  37.     D3DXVECTOR3 vecLightDirUnnormalized(x, y, z);
  38.     ZeroMemory( &light, sizeof(D3DLIGHT9) );
  39.     light.Type        = ltType;
  40.     light.Diffuse.r   = 1.0f;
  41.     light.Diffuse.g   = 1.0f;
  42.     light.Diffuse.b   = 1.0f;
  43.     D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecLightDirUnnormalized );
  44.     light.Position.x   = x;
  45.     light.Position.y   = y;
  46.     light.Position.z   = z;
  47.     light.Range        = 1000.0f;
  48. }
  49. //-----------------------------------------------------------------------------
  50. // Name: D3DUtil_CreateTexture()
  51. // Desc: Helper function to create a texture. It checks the root path first,
  52. //       then tries the DXSDK media path (as specified in the system registry).
  53. //-----------------------------------------------------------------------------
  54. HRESULT D3DUtil_CreateTexture( LPDIRECT3DDEVICE9 pd3dDevice, TCHAR* strTexture,
  55.                                LPDIRECT3DTEXTURE9* ppTexture, D3DFORMAT d3dFormat )
  56. {
  57.     HRESULT hr;
  58.     TCHAR strPath[MAX_PATH];
  59.     // Get the path to the texture
  60.     if( FAILED( hr = DXUtil_FindMediaFileCb( strPath, sizeof(strPath), strTexture ) ) )
  61.         return hr;
  62.     // Create the texture using D3DX
  63.     return D3DXCreateTextureFromFileEx( pd3dDevice, strPath, 
  64.                 D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, d3dFormat, 
  65.                 D3DPOOL_MANAGED, D3DX_FILTER_TRIANGLE|D3DX_FILTER_MIRROR, 
  66.                 D3DX_FILTER_TRIANGLE|D3DX_FILTER_MIRROR, 0, NULL, NULL, ppTexture );
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Name: D3DUtil_GetCubeMapViewMatrix()
  70. // Desc: Returns a view matrix for rendering to a face of a cubemap.
  71. //-----------------------------------------------------------------------------
  72. D3DXMATRIX D3DUtil_GetCubeMapViewMatrix( DWORD dwFace )
  73. {
  74.     D3DXVECTOR3 vEyePt   = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  75.     D3DXVECTOR3 vLookDir;
  76.     D3DXVECTOR3 vUpDir;
  77.     switch( dwFace )
  78.     {
  79.         case D3DCUBEMAP_FACE_POSITIVE_X:
  80.             vLookDir = D3DXVECTOR3( 1.0f, 0.0f, 0.0f );
  81.             vUpDir   = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  82.             break;
  83.         case D3DCUBEMAP_FACE_NEGATIVE_X:
  84.             vLookDir = D3DXVECTOR3(-1.0f, 0.0f, 0.0f );
  85.             vUpDir   = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  86.             break;
  87.         case D3DCUBEMAP_FACE_POSITIVE_Y:
  88.             vLookDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  89.             vUpDir   = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );
  90.             break;
  91.         case D3DCUBEMAP_FACE_NEGATIVE_Y:
  92.             vLookDir = D3DXVECTOR3( 0.0f,-1.0f, 0.0f );
  93.             vUpDir   = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
  94.             break;
  95.         case D3DCUBEMAP_FACE_POSITIVE_Z:
  96.             vLookDir = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
  97.             vUpDir   = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  98.             break;
  99.         case D3DCUBEMAP_FACE_NEGATIVE_Z:
  100.             vLookDir = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );
  101.             vUpDir   = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  102.             break;
  103.     }
  104.     // Set the view transform for this cubemap surface
  105.     D3DXMATRIXA16 matView;
  106.     D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookDir, &vUpDir );
  107.     return matView;
  108. }
  109. //-----------------------------------------------------------------------------
  110. // Name: D3DUtil_GetRotationFromCursor()
  111. // Desc: Returns a quaternion for the rotation implied by the window's cursor
  112. //       position.
  113. //-----------------------------------------------------------------------------
  114. D3DXQUATERNION D3DUtil_GetRotationFromCursor( HWND hWnd,
  115.                                               FLOAT fTrackBallRadius )
  116. {
  117.     POINT pt;
  118.     RECT  rc;
  119.     GetCursorPos( &pt );
  120.     GetClientRect( hWnd, &rc );
  121.     ScreenToClient( hWnd, &pt );
  122.     FLOAT sx = ( ( ( 2.0f * pt.x ) / (rc.right-rc.left) ) - 1 );
  123.     FLOAT sy = ( ( ( 2.0f * pt.y ) / (rc.bottom-rc.top) ) - 1 );
  124.     FLOAT sz;
  125.     if( sx == 0.0f && sy == 0.0f )
  126.         return D3DXQUATERNION( 0.0f, 0.0f, 0.0f, 1.0f );
  127.     FLOAT d2 = sqrtf( sx*sx + sy*sy );
  128.     if( d2 < fTrackBallRadius * 0.70710678118654752440 ) // Inside sphere
  129.         sz = sqrtf( fTrackBallRadius*fTrackBallRadius - d2*d2 );
  130.     else                                                 // On hyperbola
  131.         sz = (fTrackBallRadius*fTrackBallRadius) / (2.0f*d2);
  132.     // Get two points on trackball's sphere
  133.     D3DXVECTOR3 p1( sx, sy, sz );
  134.     D3DXVECTOR3 p2( 0.0f, 0.0f, fTrackBallRadius );
  135.     // Get axis of rotation, which is cross product of p1 and p2
  136.     D3DXVECTOR3 vAxis;
  137.     D3DXVec3Cross( &vAxis, &p1, &p2);
  138.     // Calculate angle for the rotation about that axis
  139.     D3DXVECTOR3 vecDiff = p2-p1;
  140.     FLOAT t = D3DXVec3Length( &vecDiff ) / ( 2.0f*fTrackBallRadius );
  141.     if( t > +1.0f) t = +1.0f;
  142.     if( t < -1.0f) t = -1.0f;
  143.     FLOAT fAngle = 2.0f * asinf( t );
  144.     // Convert axis to quaternion
  145.     D3DXQUATERNION quat;
  146.     D3DXQuaternionRotationAxis( &quat, &vAxis, fAngle );
  147.     return quat;
  148. }
  149. //-----------------------------------------------------------------------------
  150. // Name: D3DUtil_SetDeviceCursor
  151. // Desc: Gives the D3D device a cursor with image and hotspot from hCursor.
  152. //-----------------------------------------------------------------------------
  153. HRESULT D3DUtil_SetDeviceCursor( LPDIRECT3DDEVICE9 pd3dDevice, HCURSOR hCursor,
  154.                                  BOOL bAddWatermark )
  155. {
  156.     HRESULT hr = E_FAIL;
  157.     ICONINFO iconinfo;
  158.     BOOL bBWCursor;
  159.     LPDIRECT3DSURFACE9 pCursorSurface = NULL;
  160.     HDC hdcColor = NULL;
  161.     HDC hdcMask = NULL;
  162.     HDC hdcScreen = NULL;
  163.     BITMAP bm;
  164.     DWORD dwWidth;
  165.     DWORD dwHeightSrc;
  166.     DWORD dwHeightDest;
  167.     COLORREF crColor;
  168.     COLORREF crMask;
  169.     UINT x;
  170.     UINT y;
  171.     BITMAPINFO bmi;
  172.     COLORREF* pcrArrayColor = NULL;
  173.     COLORREF* pcrArrayMask = NULL;
  174.     DWORD* pBitmap;
  175.     HGDIOBJ hgdiobjOld;
  176.     ZeroMemory( &iconinfo, sizeof(iconinfo) );
  177.     if( !GetIconInfo( hCursor, &iconinfo ) )
  178.         goto End;
  179.     if (0 == GetObject((HGDIOBJ)iconinfo.hbmMask, sizeof(BITMAP), (LPVOID)&bm))
  180.         goto End;
  181.     dwWidth = bm.bmWidth;
  182.     dwHeightSrc = bm.bmHeight;
  183.     if( iconinfo.hbmColor == NULL )
  184.     {
  185.         bBWCursor = TRUE;
  186.         dwHeightDest = dwHeightSrc / 2;
  187.     }
  188.     else 
  189.     {
  190.         bBWCursor = FALSE;
  191.         dwHeightDest = dwHeightSrc;
  192.     }
  193.     // Create a surface for the fullscreen cursor
  194.     if( FAILED( hr = pd3dDevice->CreateOffscreenPlainSurface( dwWidth, dwHeightDest, 
  195.         D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pCursorSurface, NULL ) ) )
  196.     {
  197.         goto End;
  198.     }
  199.     pcrArrayMask = new DWORD[dwWidth * dwHeightSrc];
  200.     ZeroMemory(&bmi, sizeof(bmi));
  201.     bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
  202.     bmi.bmiHeader.biWidth = dwWidth;
  203.     bmi.bmiHeader.biHeight = dwHeightSrc;
  204.     bmi.bmiHeader.biPlanes = 1;
  205.     bmi.bmiHeader.biBitCount = 32;
  206.     bmi.bmiHeader.biCompression = BI_RGB;
  207.     hdcScreen = GetDC( NULL );
  208.     hdcMask = CreateCompatibleDC( hdcScreen );
  209.     if( hdcMask == NULL )
  210.     {
  211.         hr = E_FAIL;
  212.         goto End;
  213.     }
  214.     hgdiobjOld = SelectObject(hdcMask, iconinfo.hbmMask);
  215.     GetDIBits(hdcMask, iconinfo.hbmMask, 0, dwHeightSrc, 
  216.         pcrArrayMask, &bmi, DIB_RGB_COLORS);
  217.     SelectObject(hdcMask, hgdiobjOld);
  218.     if (!bBWCursor)
  219.     {
  220.         pcrArrayColor = new DWORD[dwWidth * dwHeightDest];
  221.         hdcColor = CreateCompatibleDC( hdcScreen );
  222.         if( hdcColor == NULL )
  223.         {
  224.             hr = E_FAIL;
  225.             goto End;
  226.         }
  227.         SelectObject(hdcColor, iconinfo.hbmColor);
  228.         GetDIBits(hdcColor, iconinfo.hbmColor, 0, dwHeightDest, 
  229.             pcrArrayColor, &bmi, DIB_RGB_COLORS);
  230.     }
  231.     // Transfer cursor image into the surface
  232.     D3DLOCKED_RECT lr;
  233.     pCursorSurface->LockRect( &lr, NULL, 0 );
  234.     pBitmap = (DWORD*)lr.pBits;
  235.     for( y = 0; y < dwHeightDest; y++ )
  236.     {
  237.         for( x = 0; x < dwWidth; x++ )
  238.         {
  239.             if (bBWCursor)
  240.             {
  241.                 crColor = pcrArrayMask[dwWidth*(dwHeightDest-1-y) + x];
  242.                 crMask = pcrArrayMask[dwWidth*(dwHeightSrc-1-y) + x];
  243.             }
  244.             else
  245.             {
  246.                 crColor = pcrArrayColor[dwWidth*(dwHeightDest-1-y) + x];
  247.                 crMask = pcrArrayMask[dwWidth*(dwHeightDest-1-y) + x];
  248.             }
  249.             if (crMask == 0)
  250.                 pBitmap[dwWidth*y + x] = 0xff000000 | crColor;
  251.             else
  252.                 pBitmap[dwWidth*y + x] = 0x00000000;
  253.             // It may be helpful to make the D3D cursor look slightly 
  254.             // different from the Windows cursor so you can distinguish 
  255.             // between the two when developing/testing code.  When
  256.             // bAddWatermark is TRUE, the following code adds some
  257.             // small grey "D3D" characters to the upper-left corner of
  258.             // the D3D cursor image.
  259.             if( bAddWatermark && x < 12 && y < 5 )
  260.             {
  261.                 // 11.. 11.. 11.. .... CCC0
  262.                 // 1.1. ..1. 1.1. .... A2A0
  263.                 // 1.1. .1.. 1.1. .... A4A0
  264.                 // 1.1. ..1. 1.1. .... A2A0
  265.                 // 11.. 11.. 11.. .... CCC0
  266.                 const WORD wMask[5] = { 0xccc0, 0xa2a0, 0xa4a0, 0xa2a0, 0xccc0 };
  267.                 if( wMask[y] & (1 << (15 - x)) )
  268.                 {
  269.                     pBitmap[dwWidth*y + x] |= 0xff808080;
  270.                 }
  271.             }
  272.         }
  273.     }
  274.     pCursorSurface->UnlockRect();
  275.     // Set the device cursor
  276.     if( FAILED( hr = pd3dDevice->SetCursorProperties( iconinfo.xHotspot, 
  277.         iconinfo.yHotspot, pCursorSurface ) ) )
  278.     {
  279.         goto End;
  280.     }
  281.     hr = S_OK;
  282. End:
  283.     if( iconinfo.hbmMask != NULL )
  284.         DeleteObject( iconinfo.hbmMask );
  285.     if( iconinfo.hbmColor != NULL )
  286.         DeleteObject( iconinfo.hbmColor );
  287.     if( hdcScreen != NULL )
  288.         ReleaseDC( NULL, hdcScreen );
  289.     if( hdcColor != NULL )
  290.         DeleteDC( hdcColor );
  291.     if( hdcMask != NULL )
  292.         DeleteDC( hdcMask );
  293.     SAFE_DELETE_ARRAY( pcrArrayColor );
  294.     SAFE_DELETE_ARRAY( pcrArrayMask );
  295.     SAFE_RELEASE( pCursorSurface );
  296.     return hr;
  297. }
  298. //-----------------------------------------------------------------------------
  299. // Name: D3DFormatToString
  300. // Desc: Returns the string for the given D3DFORMAT.
  301. //-----------------------------------------------------------------------------
  302. TCHAR* D3DUtil_D3DFormatToString( D3DFORMAT format, bool bWithPrefix )
  303. {
  304.     TCHAR* pstr = NULL;
  305.     switch( format )
  306.     {
  307.     case D3DFMT_UNKNOWN:         pstr = TEXT("D3DFMT_UNKNOWN"); break;
  308.     case D3DFMT_R8G8B8:          pstr = TEXT("D3DFMT_R8G8B8"); break;
  309.     case D3DFMT_A8R8G8B8:        pstr = TEXT("D3DFMT_A8R8G8B8"); break;
  310.     case D3DFMT_X8R8G8B8:        pstr = TEXT("D3DFMT_X8R8G8B8"); break;
  311.     case D3DFMT_R5G6B5:          pstr = TEXT("D3DFMT_R5G6B5"); break;
  312.     case D3DFMT_X1R5G5B5:        pstr = TEXT("D3DFMT_X1R5G5B5"); break;
  313.     case D3DFMT_A1R5G5B5:        pstr = TEXT("D3DFMT_A1R5G5B5"); break;
  314.     case D3DFMT_A4R4G4B4:        pstr = TEXT("D3DFMT_A4R4G4B4"); break;
  315.     case D3DFMT_R3G3B2:          pstr = TEXT("D3DFMT_R3G3B2"); break;
  316.     case D3DFMT_A8:              pstr = TEXT("D3DFMT_A8"); break;
  317.     case D3DFMT_A8R3G3B2:        pstr = TEXT("D3DFMT_A8R3G3B2"); break;
  318.     case D3DFMT_X4R4G4B4:        pstr = TEXT("D3DFMT_X4R4G4B4"); break;
  319.     case D3DFMT_A2B10G10R10:     pstr = TEXT("D3DFMT_A2B10G10R10"); break;
  320.     case D3DFMT_A8B8G8R8:        pstr = TEXT("D3DFMT_A8B8G8R8"); break;
  321.     case D3DFMT_X8B8G8R8:        pstr = TEXT("D3DFMT_X8B8G8R8"); break;
  322.     case D3DFMT_G16R16:          pstr = TEXT("D3DFMT_G16R16"); break;
  323.     case D3DFMT_A2R10G10B10:     pstr = TEXT("D3DFMT_A2R10G10B10"); break;
  324.     case D3DFMT_A16B16G16R16:    pstr = TEXT("D3DFMT_A16B16G16R16"); break;
  325.     case D3DFMT_A8P8:            pstr = TEXT("D3DFMT_A8P8"); break;
  326.     case D3DFMT_P8:              pstr = TEXT("D3DFMT_P8"); break;
  327.     case D3DFMT_L8:              pstr = TEXT("D3DFMT_L8"); break;
  328.     case D3DFMT_A8L8:            pstr = TEXT("D3DFMT_A8L8"); break;
  329.     case D3DFMT_A4L4:            pstr = TEXT("D3DFMT_A4L4"); break;
  330.     case D3DFMT_V8U8:            pstr = TEXT("D3DFMT_V8U8"); break;
  331.     case D3DFMT_L6V5U5:          pstr = TEXT("D3DFMT_L6V5U5"); break;
  332.     case D3DFMT_X8L8V8U8:        pstr = TEXT("D3DFMT_X8L8V8U8"); break;
  333.     case D3DFMT_Q8W8V8U8:        pstr = TEXT("D3DFMT_Q8W8V8U8"); break;
  334.     case D3DFMT_V16U16:          pstr = TEXT("D3DFMT_V16U16"); break;
  335.     case D3DFMT_A2W10V10U10:     pstr = TEXT("D3DFMT_A2W10V10U10"); break;
  336.     case D3DFMT_UYVY:            pstr = TEXT("D3DFMT_UYVY"); break;
  337.     case D3DFMT_YUY2:            pstr = TEXT("D3DFMT_YUY2"); break;
  338.     case D3DFMT_DXT1:            pstr = TEXT("D3DFMT_DXT1"); break;
  339.     case D3DFMT_DXT2:            pstr = TEXT("D3DFMT_DXT2"); break;
  340.     case D3DFMT_DXT3:            pstr = TEXT("D3DFMT_DXT3"); break;
  341.     case D3DFMT_DXT4:            pstr = TEXT("D3DFMT_DXT4"); break;
  342.     case D3DFMT_DXT5:            pstr = TEXT("D3DFMT_DXT5"); break;
  343.     case D3DFMT_D16_LOCKABLE:    pstr = TEXT("D3DFMT_D16_LOCKABLE"); break;
  344.     case D3DFMT_D32:             pstr = TEXT("D3DFMT_D32"); break;
  345.     case D3DFMT_D15S1:           pstr = TEXT("D3DFMT_D15S1"); break;
  346.     case D3DFMT_D24S8:           pstr = TEXT("D3DFMT_D24S8"); break;
  347.     case D3DFMT_D24X8:           pstr = TEXT("D3DFMT_D24X8"); break;
  348.     case D3DFMT_D24X4S4:         pstr = TEXT("D3DFMT_D24X4S4"); break;
  349.     case D3DFMT_D16:             pstr = TEXT("D3DFMT_D16"); break;
  350.     case D3DFMT_L16:             pstr = TEXT("D3DFMT_L16"); break;
  351.     case D3DFMT_VERTEXDATA:      pstr = TEXT("D3DFMT_VERTEXDATA"); break;
  352.     case D3DFMT_INDEX16:         pstr = TEXT("D3DFMT_INDEX16"); break;
  353.     case D3DFMT_INDEX32:         pstr = TEXT("D3DFMT_INDEX32"); break;
  354.     case D3DFMT_Q16W16V16U16:    pstr = TEXT("D3DFMT_Q16W16V16U16"); break;
  355.     case D3DFMT_MULTI2_ARGB8:    pstr = TEXT("D3DFMT_MULTI2_ARGB8"); break;
  356.     case D3DFMT_R16F:            pstr = TEXT("D3DFMT_R16F"); break;
  357.     case D3DFMT_G16R16F:         pstr = TEXT("D3DFMT_G16R16F"); break;
  358.     case D3DFMT_A16B16G16R16F:   pstr = TEXT("D3DFMT_A16B16G16R16F"); break;
  359.     case D3DFMT_R32F:            pstr = TEXT("D3DFMT_R32F"); break;
  360.     case D3DFMT_G32R32F:         pstr = TEXT("D3DFMT_G32R32F"); break;
  361.     case D3DFMT_A32B32G32R32F:   pstr = TEXT("D3DFMT_A32B32G32R32F"); break;
  362.     case D3DFMT_CxV8U8:          pstr = TEXT("D3DFMT_CxV8U8"); break;
  363.     default:                     pstr = TEXT("Unknown format"); break;
  364.     }
  365.     if( bWithPrefix || _tcsstr( pstr, TEXT("D3DFMT_") )== NULL )
  366.         return pstr;
  367.     else
  368.         return pstr + lstrlen( TEXT("D3DFMT_") );
  369. }
  370. //-----------------------------------------------------------------------------
  371. // Name: D3DXQuaternionUnitAxisToUnitAxis2
  372. // Desc: Axis to axis quaternion double angle (no normalization)
  373. //       Takes two points on unit sphere an angle THETA apart, returns
  374. //       quaternion that represents a rotation around cross product by 2*THETA.
  375. //-----------------------------------------------------------------------------
  376. inline D3DXQUATERNION* WINAPI D3DXQuaternionUnitAxisToUnitAxis2
  377. ( D3DXQUATERNION *pOut, const D3DXVECTOR3 *pvFrom, const D3DXVECTOR3 *pvTo)
  378. {
  379.     D3DXVECTOR3 vAxis;
  380.     D3DXVec3Cross(&vAxis, pvFrom, pvTo);    // proportional to sin(theta)
  381.     pOut->x = vAxis.x;
  382.     pOut->y = vAxis.y;
  383.     pOut->z = vAxis.z;
  384.     pOut->w = D3DXVec3Dot( pvFrom, pvTo );
  385.     return pOut;
  386. }
  387. //-----------------------------------------------------------------------------
  388. // Name: D3DXQuaternionAxisToAxis
  389. // Desc: Axis to axis quaternion 
  390. //       Takes two points on unit sphere an angle THETA apart, returns
  391. //       quaternion that represents a rotation around cross product by theta.
  392. //-----------------------------------------------------------------------------
  393. inline D3DXQUATERNION* WINAPI D3DXQuaternionAxisToAxis
  394. ( D3DXQUATERNION *pOut, const D3DXVECTOR3 *pvFrom, const D3DXVECTOR3 *pvTo)
  395. {
  396.     D3DXVECTOR3 vA, vB;
  397.     D3DXVec3Normalize(&vA, pvFrom);
  398.     D3DXVec3Normalize(&vB, pvTo);
  399.     D3DXVECTOR3 vHalf(vA + vB);
  400.     D3DXVec3Normalize(&vHalf, &vHalf);
  401.     return D3DXQuaternionUnitAxisToUnitAxis2(pOut, &vA, &vHalf);
  402. }
  403. //-----------------------------------------------------------------------------
  404. // Name:
  405. // Desc:
  406. //-----------------------------------------------------------------------------
  407. CD3DArcBall::CD3DArcBall()
  408. {
  409.     Init();
  410. }
  411. //-----------------------------------------------------------------------------
  412. // Name:
  413. // Desc:
  414. //-----------------------------------------------------------------------------
  415. void CD3DArcBall::Init()
  416. {
  417.     D3DXQuaternionIdentity( &m_qDown );
  418.     D3DXQuaternionIdentity( &m_qNow );
  419.     D3DXMatrixIdentity( &m_matRotation );
  420.     D3DXMatrixIdentity( &m_matRotationDelta );
  421.     D3DXMatrixIdentity( &m_matTranslation );
  422.     D3DXMatrixIdentity( &m_matTranslationDelta );
  423.     m_bDrag = FALSE;
  424.     m_fRadiusTranslation = 1.0f;
  425.     m_bRightHanded = FALSE;
  426. }
  427. //-----------------------------------------------------------------------------
  428. // Name:
  429. // Desc:
  430. //-----------------------------------------------------------------------------
  431. VOID CD3DArcBall::SetWindow( int iWidth, int iHeight, float fRadius )
  432. {
  433.     // Set ArcBall info
  434.     m_iWidth  = iWidth;
  435.     m_iHeight = iHeight;
  436.     m_fRadius = fRadius;
  437. }
  438. //-----------------------------------------------------------------------------
  439. // Name:
  440. // Desc:
  441. //-----------------------------------------------------------------------------
  442. D3DXVECTOR3 CD3DArcBall::ScreenToVector( int sx, int sy )
  443. {
  444.     // Scale to screen
  445.     FLOAT x   = -(sx - m_iWidth/2)  / (m_fRadius*m_iWidth/2);
  446.     FLOAT y   =  (sy - m_iHeight/2) / (m_fRadius*m_iHeight/2);
  447.     if( m_bRightHanded )
  448.     {
  449.         x = -x;
  450.         y = -y;
  451.     }
  452.     FLOAT z   = 0.0f;
  453.     FLOAT mag = x*x + y*y;
  454.     if( mag > 1.0f )
  455.     {
  456.         FLOAT scale = 1.0f/sqrtf(mag);
  457.         x *= scale;
  458.         y *= scale;
  459.     }
  460.     else
  461.         z = sqrtf( 1.0f - mag );
  462.     // Return vector
  463.     return D3DXVECTOR3( x, y, z );
  464. }
  465. //-----------------------------------------------------------------------------
  466. // Name:
  467. // Desc:
  468. //-----------------------------------------------------------------------------
  469. VOID CD3DArcBall::SetRadius( FLOAT fRadius )
  470. {
  471.     m_fRadiusTranslation = fRadius;
  472. }
  473. //-----------------------------------------------------------------------------
  474. // Name:
  475. // Desc:
  476. //-----------------------------------------------------------------------------
  477. LRESULT CD3DArcBall::HandleMouseMessages( HWND hWnd, UINT uMsg, WPARAM wParam,
  478.                                           LPARAM lParam )
  479. {
  480.     UNREFERENCED_PARAMETER( hWnd );
  481.     static int         iCurMouseX;      // Saved mouse position
  482.     static int         iCurMouseY;
  483.     static D3DXVECTOR3 s_vDown;         // Button down vector
  484.     // Current mouse position
  485.     int iMouseX = GET_X_LPARAM(lParam);
  486.     int iMouseY = GET_Y_LPARAM(lParam);
  487.     switch( uMsg )
  488.     {
  489.         case WM_RBUTTONDOWN:
  490.         case WM_MBUTTONDOWN:
  491.             // Store off the position of the cursor when the button is pressed
  492.             iCurMouseX = iMouseX;
  493.             iCurMouseY = iMouseY;
  494.             return TRUE;
  495.         case WM_LBUTTONDOWN:
  496.             // Start drag mode
  497.             m_bDrag = TRUE;
  498.             s_vDown = ScreenToVector( iMouseX, iMouseY );
  499.             m_qDown = m_qNow;
  500.             return TRUE;
  501.         case WM_LBUTTONUP:
  502.             // End drag mode
  503.             m_bDrag = FALSE;
  504.             return TRUE;
  505.         case WM_MOUSEMOVE:
  506.             // Drag object
  507.             if( MK_LBUTTON&wParam )
  508.             {
  509.                 if( m_bDrag )
  510.                 {
  511.                     // recompute m_qNow
  512.                     D3DXVECTOR3 vCur = ScreenToVector( iMouseX, iMouseY );
  513.                     D3DXQUATERNION qAxisToAxis;
  514.                     D3DXQuaternionAxisToAxis(&qAxisToAxis, &s_vDown, &vCur);
  515.                     m_qNow = m_qDown;
  516.                     m_qNow *= qAxisToAxis;
  517.                     D3DXMatrixRotationQuaternion(&m_matRotationDelta, &qAxisToAxis);
  518.                 }
  519.                 else
  520.                     D3DXMatrixIdentity(&m_matRotationDelta);
  521.                 D3DXMatrixRotationQuaternion(&m_matRotation, &m_qNow);
  522.                 m_bDrag = TRUE;
  523.             }
  524.             else if( (MK_RBUTTON&wParam) || (MK_MBUTTON&wParam) )
  525.             {
  526.                 // Normalize based on size of window and bounding sphere radius
  527.                 FLOAT fDeltaX = ( iCurMouseX-iMouseX ) * m_fRadiusTranslation / m_iWidth;
  528.                 FLOAT fDeltaY = ( iCurMouseY-iMouseY ) * m_fRadiusTranslation / m_iHeight;
  529.                 if( wParam & MK_RBUTTON )
  530.                 {
  531.                     D3DXMatrixTranslation( &m_matTranslationDelta, -2*fDeltaX, 2*fDeltaY, 0.0f );
  532.                     D3DXMatrixMultiply( &m_matTranslation, &m_matTranslation, &m_matTranslationDelta );
  533.                 }
  534.                 else  // wParam & MK_MBUTTON
  535.                 {
  536.                     D3DXMatrixTranslation( &m_matTranslationDelta, 0.0f, 0.0f, 5*fDeltaY );
  537.                     D3DXMatrixMultiply( &m_matTranslation, &m_matTranslation, &m_matTranslationDelta );
  538.                 }
  539.                 // Store mouse coordinate
  540.                 iCurMouseX = iMouseX;
  541.                 iCurMouseY = iMouseY;
  542.             }
  543.             return TRUE;
  544.     }
  545.     return FALSE;
  546. }
  547. //-----------------------------------------------------------------------------
  548. // Name:
  549. // Desc:
  550. //-----------------------------------------------------------------------------
  551. CD3DCamera::CD3DCamera()
  552. {
  553.     // Set attributes for the view matrix
  554.     D3DXVECTOR3 vEyePt(0.0f,0.0f,0.0f);
  555.     D3DXVECTOR3 vLookatPt(0.0f,0.0f,1.0f);
  556.     D3DXVECTOR3 vUpVec(0.0f,1.0f,0.0f);
  557.     SetViewParams( vEyePt, vLookatPt, vUpVec );
  558.     // Set attributes for the projection matrix
  559.     SetProjParams( D3DX_PI/4, 1.0f, 1.0f, 1000.0f );
  560. }
  561. //-----------------------------------------------------------------------------
  562. // Name:
  563. // Desc:
  564. //-----------------------------------------------------------------------------
  565. VOID CD3DCamera::SetViewParams( D3DXVECTOR3 &vEyePt, D3DXVECTOR3& vLookatPt,
  566.                                 D3DXVECTOR3& vUpVec )
  567. {
  568.     // Set attributes for the view matrix
  569.     m_vEyePt    = vEyePt;
  570.     m_vLookatPt = vLookatPt;
  571.     m_vUpVec    = vUpVec;
  572.     D3DXVECTOR3 vDir = m_vLookatPt - m_vEyePt;
  573.     D3DXVec3Normalize( &m_vView, &vDir );
  574.     D3DXVec3Cross( &m_vCross, &m_vView, &m_vUpVec );
  575.     D3DXMatrixLookAtLH( &m_matView, &m_vEyePt, &m_vLookatPt, &m_vUpVec );
  576.     D3DXMatrixInverse( &m_matBillboard, NULL, &m_matView );
  577.     m_matBillboard._41 = 0.0f;
  578.     m_matBillboard._42 = 0.0f;
  579.     m_matBillboard._43 = 0.0f;
  580. }
  581. //-----------------------------------------------------------------------------
  582. // Name:
  583. // Desc:
  584. //-----------------------------------------------------------------------------
  585. VOID CD3DCamera::SetProjParams( FLOAT fFOV, FLOAT fAspect, FLOAT fNearPlane,
  586.                                 FLOAT fFarPlane )
  587. {
  588.     // Set attributes for the projection matrix
  589.     m_fFOV        = fFOV;
  590.     m_fAspect     = fAspect;
  591.     m_fNearPlane  = fNearPlane;
  592.     m_fFarPlane   = fFarPlane;
  593.     D3DXMatrixPerspectiveFovLH( &m_matProj, fFOV, fAspect, fNearPlane, fFarPlane );
  594. }