home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / SkinnedMesh / skinnedmesh.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  19.8 KB  |  605 lines

  1. //-----------------------------------------------------------------------------
  2. // File: SkinnedMesh.cpp
  3. //
  4. // Desc: Example code showing how to use animated models with skinning.
  5. //
  6. // Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #include <tchar.h>
  10. #include <stdio.h>
  11. #include <windows.h>
  12. #include <mmsystem.h>
  13. #include <commdlg.h>
  14. #include <tchar.h>
  15. #include <d3d8.h>
  16. #include <d3dx8.h>
  17. #include "resource.h"
  18. #include "D3DApp.h"
  19. #include "D3DFont.h"
  20. #include "D3DUtil.h"
  21. #include "DXUtil.h"
  22. #include "SkinnedMesh.h"
  23.  
  24.  
  25.  
  26.  
  27. //-----------------------------------------------------------------------------
  28. // Name: WinMain()
  29. // Desc: Entry point to the program. Initializes everything, and goes into a
  30. //       message-processing loop. Idle time is used to render the scene.
  31. //-----------------------------------------------------------------------------
  32. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  33. {
  34.     CMyD3DApplication d3dApp;
  35.  
  36.     if( FAILED( d3dApp.Create( hInst ) ) )
  37.         return 0;
  38.  
  39.     return d3dApp.Run();
  40. }
  41.  
  42.  
  43.  
  44.  
  45. //-----------------------------------------------------------------------------
  46. // Name: CMyD3DApplication()
  47. // Desc: Application constructor. Sets attributes for the app.
  48. //-----------------------------------------------------------------------------
  49. CMyD3DApplication::CMyD3DApplication()
  50. {
  51.     m_strWindowTitle    = _T("Skinned Mesh");
  52.     m_bUseDepthBuffer   = TRUE;
  53.     m_bShowCursorWhenFullscreen = TRUE;
  54.  
  55.     m_pFont  = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  56.  
  57.     m_pmcSelectedMesh = NULL;
  58.     m_pframeSelected = NULL;
  59.     m_pdeHead = NULL;
  60.     m_pdeSelected = NULL;
  61.  
  62.     m_dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL | D3DFVF_TEX1;
  63.  
  64.     m_method = D3DNONINDEXED;
  65.  
  66.     m_pBoneMatrices = NULL;
  67.     m_maxBones = 0;
  68.  
  69.     m_szPath[0] = '\0';
  70. }
  71.  
  72.  
  73.  
  74.  
  75. //-----------------------------------------------------------------------------
  76. // Name: ConfirmDevice()
  77. // Desc: Called during device intialization, this code checks the device
  78. //       for some minimum set of capabilities
  79. //-----------------------------------------------------------------------------
  80. HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,
  81.                                           D3DFORMAT Format )
  82. {
  83.     // This sample wants mixed vertex processing rather than hardware
  84.     // vertex processing so it can fallback to sw processing if the 
  85.     // device supports fewer than three matrices when skinning.
  86.     if( dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING )
  87.         return E_FAIL;
  88.  
  89.     return S_OK;
  90. }
  91.  
  92.  
  93.  
  94.  
  95. //-----------------------------------------------------------------------------
  96. // Name: OneTimeSceneInit()
  97. // Desc: Called during initial app startup, this function performs all the
  98. //       permanent initialization.
  99. //-----------------------------------------------------------------------------
  100. HRESULT CMyD3DApplication::OneTimeSceneInit()
  101. {
  102.     // Set cursor to indicate that user can move the object with the mouse
  103. #ifdef _WIN64
  104.     SetClassLongPtr( m_hWnd, GCLP_HCURSOR, (LONG_PTR)LoadCursor( NULL, IDC_SIZEALL ) );
  105. #else
  106.     SetClassLong( m_hWnd, GCL_HCURSOR, (LONG)LoadCursor( NULL, IDC_SIZEALL ) );
  107. #endif
  108.     return S_OK;
  109. }
  110.  
  111.  
  112.  
  113.  
  114. //-----------------------------------------------------------------------------
  115. // Name: FrameMove()
  116. // Desc: Called once per frame, the call is the entry point for animating
  117. //       the scene.
  118. //-----------------------------------------------------------------------------
  119. HRESULT CMyD3DApplication::FrameMove()
  120. {
  121.     SDrawElement *pdeCur;
  122.     SFrame *pframeCur;
  123.  
  124.     pdeCur = m_pdeHead;
  125.     while (pdeCur != NULL)
  126.     {
  127.         pdeCur->fCurTime += m_fElapsedTime * 4800;
  128.         if (pdeCur->fCurTime > 1.0e15f)
  129.             pdeCur->fCurTime = 0;
  130.  
  131.         pframeCur = pdeCur->pframeAnimHead;
  132.         while (pframeCur != NULL)
  133.         {
  134.             pframeCur->SetTime(pdeCur->fCurTime);
  135.             pframeCur = pframeCur->pframeAnimNext;
  136.         }
  137.  
  138.         pdeCur = pdeCur->pdeNext;
  139.     }
  140.     
  141.     return S_OK;
  142. }
  143.  
  144.  
  145.  
  146.  
  147. //-----------------------------------------------------------------------------
  148. // Name: Render()
  149. // Desc: Called once per frame, the call is the entry point for 3d
  150. //       rendering. This function sets up render states, clears the
  151. //       viewport, and renders the scene.
  152. //-----------------------------------------------------------------------------
  153. HRESULT CMyD3DApplication::Render()
  154. {
  155.     // Set up viewing postion from ArcBall
  156.     SDrawElement *pdeCur;
  157.     D3DXMATRIXA16 mat;
  158.     pdeCur = m_pdeHead;
  159.     while (pdeCur != NULL)
  160.     {
  161.         pdeCur->pframeRoot->matRot = *m_ArcBall.GetRotationMatrix();
  162.         pdeCur->pframeRoot->matTrans = *m_ArcBall.GetTranslationMatrix();
  163.         pdeCur = pdeCur->pdeNext;
  164.     }
  165.     
  166.     // Clear the viewport
  167.     m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(89,135,179), 1.0f, 0 );
  168.  
  169.     if (m_pdeHead == NULL)
  170.     {
  171.         return S_OK;
  172.     }
  173.  
  174.     // Begin the scene 
  175.     if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
  176.     {
  177.         UINT cTriangles = 0;
  178.         HRESULT hr;
  179.         SDrawElement *pdeCur;
  180.         D3DXMATRIXA16 mCur;
  181.         D3DXVECTOR3 vTemp;
  182.  
  183.         D3DXMatrixTranslation(&m_mView, 0, 0, -m_pdeSelected->fRadius * 2.8f);
  184.  
  185.         hr = m_pd3dDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&m_mView);
  186.         if(FAILED(hr))
  187.             return hr;
  188.  
  189.         pdeCur = m_pdeHead;
  190.         while (pdeCur != NULL)
  191.         {
  192.             D3DXMatrixIdentity(&mCur);
  193.  
  194.             hr = UpdateFrames(pdeCur->pframeRoot, mCur);
  195.             if (FAILED(hr))
  196.                 return hr;
  197.             hr = DrawFrames(pdeCur->pframeRoot, cTriangles);
  198.             if (FAILED(hr))
  199.                 return hr;
  200.  
  201.             pdeCur = pdeCur->pdeNext;
  202.         }
  203.  
  204.         // Show frame rate
  205.         m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  206.         m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  207.  
  208.         // End the scene.
  209.         m_pd3dDevice->EndScene();   
  210.     }
  211.  
  212.     return S_OK;
  213. }
  214.  
  215.  
  216.  
  217.  
  218. //-----------------------------------------------------------------------------
  219. // Name: InitDeviceObjects()
  220. // Desc: Initialize scene objects.
  221. //-----------------------------------------------------------------------------
  222. HRESULT CMyD3DApplication::InitDeviceObjects()
  223. {
  224.     HRESULT hr = S_OK;
  225.  
  226.     // Restore the fonts
  227.     m_pFont->InitDeviceObjects( m_pd3dDevice );
  228.  
  229.     // if no filename, use the default
  230.     if (m_szPath[0] == '\0')
  231.     {
  232.         DXUtil_FindMediaFile( m_szPath, _T("tiny.x") );
  233.     }
  234.  
  235.     LoadMeshHierarchy();
  236.  
  237.     if( m_pdeHead != NULL)
  238.         m_ArcBall.SetRadius( m_pdeHead->fRadius );
  239.     m_ArcBall.SetRightHanded( TRUE );
  240.     
  241.     return S_OK;
  242. }
  243.  
  244.  
  245.  
  246.  
  247. //-----------------------------------------------------------------------------
  248. // Name: RestoreDeviceObjects()
  249. // Desc: Initialize scene objects.
  250. //-----------------------------------------------------------------------------
  251. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  252. {
  253.     // Restore the fonts
  254.     m_pFont->RestoreDeviceObjects();
  255.  
  256.     HRESULT hr = S_OK;
  257.     D3DLIGHT8 light;
  258.  
  259.     m_ArcBall.SetWindow( m_d3dsdBackBuffer.Width, m_d3dsdBackBuffer.Height, 2.0f );
  260.  
  261.     if (m_pdeSelected != NULL)
  262.         SetProjectionMatrix();
  263.  
  264.     m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE );
  265.     m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
  266.     m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE );
  267.     m_pd3dDevice->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE );
  268.  
  269.     m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
  270.     m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
  271.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR  );
  272.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR  );
  273.  
  274.     m_pd3dDevice->SetRenderState( D3DRS_COLORVERTEX, FALSE );
  275.  
  276.     // Create vertex shader for the indexed skinning
  277.     DWORD dwIndexedVertexDecl1[] =
  278.     {
  279.         D3DVSD_STREAM( 0 ),
  280.         D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // Position of first mesh
  281.         D3DVSD_REG( 2, D3DVSDT_D3DCOLOR ), // Blend indices
  282. //        D3DVSD_REG( 2, D3DVSDT_UBYTE4 ), // Blend indices
  283.         D3DVSD_REG( 3, D3DVSDT_FLOAT3 ), // Normal
  284.         D3DVSD_REG( 4, D3DVSDT_FLOAT2 ), // Tex coords
  285.         D3DVSD_END()
  286.     };
  287.  
  288.     DWORD dwIndexedVertexDecl2[] =
  289.     {
  290.         D3DVSD_STREAM( 0 ),
  291.         D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // Position of first mesh
  292.         D3DVSD_REG( 1, D3DVSDT_FLOAT1 ), // Blend weights
  293.         D3DVSD_REG( 2, D3DVSDT_D3DCOLOR ), // Blend indices
  294. //        D3DVSD_REG( 2, D3DVSDT_UBYTE4 ), // Blend indices
  295.         D3DVSD_REG( 3, D3DVSDT_FLOAT3 ), // Normal
  296.         D3DVSD_REG( 4, D3DVSDT_FLOAT2 ), // Tex coords
  297.         D3DVSD_END()
  298.     };
  299.  
  300.     DWORD dwIndexedVertexDecl3[] =
  301.     {
  302.         D3DVSD_STREAM( 0 ),
  303.         D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // Position of first mesh
  304.         D3DVSD_REG( 1, D3DVSDT_FLOAT2 ), // Blend weights
  305.         D3DVSD_REG( 2, D3DVSDT_D3DCOLOR ), // Blend indices
  306. //        D3DVSD_REG( 2, D3DVSDT_UBYTE4 ), // Blend indices
  307.         D3DVSD_REG( 3, D3DVSDT_FLOAT3 ), // Normal
  308.         D3DVSD_REG( 4, D3DVSDT_FLOAT2 ), // Tex coords
  309.         D3DVSD_END()
  310.     };
  311.  
  312.     DWORD dwIndexedVertexDecl4[] =
  313.     {
  314.         D3DVSD_STREAM( 0 ),
  315.         D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // Position of first mesh
  316.         D3DVSD_REG( 1, D3DVSDT_FLOAT3 ), // Blend weights
  317.         D3DVSD_REG( 2, D3DVSDT_D3DCOLOR ), // Blend indices
  318. //        D3DVSD_REG( 2, D3DVSDT_UBYTE4 ), // Blend indices
  319.         D3DVSD_REG( 3, D3DVSDT_FLOAT3 ), // Normal
  320.         D3DVSD_REG( 4, D3DVSDT_FLOAT2 ), // Tex coords
  321.         D3DVSD_END()
  322.     };
  323.  
  324.     DWORD* dwIndexedVertexDecl[] = {dwIndexedVertexDecl1, dwIndexedVertexDecl2, dwIndexedVertexDecl3, dwIndexedVertexDecl4};
  325.  
  326.     LPD3DXBUFFER pCode;
  327.  
  328.     DWORD bUseSW = D3DUSAGE_SOFTWAREPROCESSING;
  329.     if (m_d3dCaps.VertexShaderVersion >= D3DVS_VERSION(1, 1))
  330.     {
  331.         bUseSW = 0;
  332.     }
  333.  
  334.     for (DWORD i = 0; i < 4; ++i)
  335.     {
  336.         // Assemble the vertex shader file
  337.         if( FAILED( hr = D3DXAssembleShaderFromResource(NULL, MAKEINTRESOURCE(IDD_SHADER1 + i), 0, NULL, &pCode, NULL ) ) )
  338.             return hr;
  339.  
  340.         // Create the vertex shader
  341.         if( FAILED( hr = m_pd3dDevice->CreateVertexShader( dwIndexedVertexDecl[i], 
  342.                                              (DWORD*)pCode->GetBufferPointer(),
  343.                                              &(m_dwIndexedVertexShader[i]) , bUseSW ) ) )
  344.         {
  345.             return hr;
  346.         }
  347.  
  348.         pCode->Release();
  349.     }
  350.     
  351.     ZeroMemory( &light, sizeof(light) );
  352.     light.Type = D3DLIGHT_DIRECTIONAL;
  353.  
  354.     light.Diffuse.r = 1.0;
  355.     light.Diffuse.g = 1.0;
  356.     light.Diffuse.b = 1.0;
  357.     light.Specular.r = 0;
  358.     light.Specular.g = 0;
  359.     light.Specular.b = 0;
  360.     light.Ambient.r = 0.25;
  361.     light.Ambient.g = 0.25;
  362.     light.Ambient.b = 0.25;
  363.  
  364.     light.Direction = D3DXVECTOR3( 0.0f, 0.0f, -1.0f);
  365.  
  366.     hr = m_pd3dDevice->SetLight(0, &light );
  367.     if (FAILED(hr))
  368.         return E_FAIL;
  369.  
  370.     hr = m_pd3dDevice->LightEnable(0, TRUE);
  371.     if (FAILED(hr))
  372.         return E_FAIL;
  373.  
  374.     // Set Light for vertex shader
  375.     D3DXVECTOR4 vLightDir( 0.0f, 0.0f, 1.0f, 0.0f );
  376.     m_pd3dDevice->SetVertexShaderConstant(1, &vLightDir, 1);
  377.  
  378.     return S_OK;
  379. }
  380.  
  381.  
  382.  
  383.  
  384. //-----------------------------------------------------------------------------
  385. // Name: ReleaseDeviceDependentMeshes()
  386. // Desc: 
  387. //-----------------------------------------------------------------------------
  388. void ReleaseDeviceDependentMeshes(SFrame* pframe)
  389. {
  390.     if (pframe->pmcMesh != NULL)
  391.     {
  392.         for (SMeshContainer* pmcCurr = pframe->pmcMesh; pmcCurr != NULL; pmcCurr = pmcCurr->pmcNext)
  393.         {
  394.             if (pmcCurr->m_pSkinMesh != NULL)
  395.             {
  396.                 GXRELEASE(pmcCurr->pMesh);
  397.  
  398.                 pmcCurr->m_Method = NONE;
  399.             }
  400.         }
  401.     }
  402.  
  403.     if (pframe->pframeFirstChild != NULL)
  404.         ReleaseDeviceDependentMeshes(pframe->pframeFirstChild);
  405.  
  406.     if (pframe->pframeSibling != NULL)
  407.         ReleaseDeviceDependentMeshes(pframe->pframeSibling);
  408. }
  409.  
  410.  
  411.  
  412.  
  413. //-----------------------------------------------------------------------------
  414. // Name: InvalidateDeviceObjects()
  415. // Desc: Called when the app is exiting, or the device is being changed,
  416. //       this function deletes any device dependent objects.
  417. //-----------------------------------------------------------------------------
  418. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  419. {
  420.     m_pFont->InvalidateDeviceObjects();
  421.  
  422.  
  423.     for (SDrawElement* pdeCurr = m_pdeHead; pdeCurr != NULL; pdeCurr = pdeCurr->pdeNext)
  424.     {
  425.         ReleaseDeviceDependentMeshes(pdeCurr->pframeRoot);
  426.     }
  427.  
  428.     return S_OK;
  429. }
  430.  
  431.  
  432.  
  433.  
  434. //-----------------------------------------------------------------------------
  435. // Name: DeleteDeviceObjects()
  436. // Desc: Called when the app is exiting, or the device is being changed,
  437. //       this function deletes any device dependent objects.
  438. //-----------------------------------------------------------------------------
  439. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  440. {
  441.     m_pFont->DeleteDeviceObjects();
  442.     
  443.     if( m_pdeSelected == m_pdeHead )
  444.         m_pdeSelected = NULL;
  445.  
  446.     delete m_pdeHead;
  447.     m_pdeHead = NULL;
  448.     
  449.     delete [] m_pBoneMatrices;
  450.  
  451.     return S_OK;
  452. }
  453.  
  454.  
  455.  
  456.  
  457. //-----------------------------------------------------------------------------
  458. // Name: FinalCleanup()
  459. // Desc: Called before the app exits, this function gives the app the chance
  460. //       to cleanup after itself.
  461. //-----------------------------------------------------------------------------
  462. HRESULT CMyD3DApplication::FinalCleanup()
  463. {
  464.     SAFE_DELETE( m_pFont );
  465.  
  466.     return S_OK;
  467. }
  468.  
  469.  
  470.  
  471.  
  472. //-----------------------------------------------------------------------------
  473. // Name: MsgProc()
  474. // Desc: Message proc function to handle key and menu input
  475. //-----------------------------------------------------------------------------
  476. LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
  477.                                     LPARAM lParam )
  478. {
  479.     // Pass mouse messages to the ArcBall so it can build internal matrices
  480.     m_ArcBall.HandleMouseMessages( hWnd, uMsg, wParam, lParam );
  481.  
  482.     switch( uMsg )
  483.     {
  484.     case WM_COMMAND:
  485.         if ( 0 == HIWORD(wParam) )
  486.         {
  487.             switch ( LOWORD(wParam) )
  488.             {                
  489.             case ID_FILE_OPENMESHHEIRARCHY:
  490.                 {
  491.                     OPENFILENAME ofn;
  492.                     memset( &ofn, 0, sizeof(ofn) );
  493.                     static TCHAR file[256];
  494.                     static TCHAR szFilepath[256];
  495.                     static TCHAR fileTitle[256];
  496.                     static TCHAR filter[] =
  497.                         TEXT("X files (*.x)\0*.x\0")
  498.                         TEXT("All Files (*.*)\0*.*\0");
  499.                     _tcscpy( file, TEXT(""));
  500.                     _tcscpy( fileTitle, TEXT(""));
  501.                     
  502.                     ofn.lStructSize       = sizeof(ofn);
  503.                     ofn.hwndOwner         = m_hWnd;
  504.                     ofn.hInstance         = NULL;//m_hInstance;
  505.                     ofn.lpstrFilter       = filter;
  506.                     ofn.lpstrCustomFilter = NULL;
  507.                     ofn.nMaxCustFilter    = 0L;
  508.                     ofn.nFilterIndex      = 1L;
  509.                     ofn.lpstrFile         = file;
  510.                     ofn.nMaxFile          = sizeof(file);
  511.                     ofn.lpstrFileTitle    = fileTitle;
  512.                     ofn.nMaxFileTitle     = sizeof(fileTitle);
  513.                     ofn.lpstrInitialDir   = NULL;
  514.                     ofn.nFileOffset       = 0;
  515.                     ofn.nFileExtension    = 0;
  516.                     ofn.lpstrDefExt       = TEXT("*.x");
  517.                     ofn.lCustData         = 0;
  518.                     
  519.                     ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  520.                     if ( ! GetOpenFileName( &ofn) )
  521.                     {
  522.                         TCHAR s[40];
  523.                         DWORD dwErr = CommDlgExtendedError();
  524.                         if ( 0 != dwErr )
  525.                         {
  526.                             wsprintf( s, "GetOpenFileName failed with %x", dwErr );
  527.                             MessageBox( m_hWnd, s, "TexWin", MB_OK | MB_SYSTEMMODAL );
  528.                         }
  529.                         return 0;
  530.                     }
  531.                     lstrcpy(m_szPath, ofn.lpstrFile);
  532.                     HRESULT hr = LoadMeshHierarchy();
  533.                     if (FAILED(hr))
  534.                         MessageBox(NULL, "Could not open file or incorrect file type", "Error loading file", MB_OK);
  535.  
  536.                     return 0;
  537.                 }
  538.             case ID_OPTIONS_D3DINDEXED:
  539.                 {
  540.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DINDEXED, MF_CHECKED);
  541.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DNONINDEXED, MF_UNCHECKED);
  542.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_SOFTWARESKINNING, MF_UNCHECKED);
  543.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DINDEXEDVS, MF_UNCHECKED);
  544.                     m_method = D3DINDEXED;
  545.                     break;
  546.                 }
  547.             case ID_OPTIONS_D3DINDEXEDVS:
  548.                 {
  549.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DINDEXED, MF_UNCHECKED);
  550.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DNONINDEXED, MF_UNCHECKED);
  551.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_SOFTWARESKINNING, MF_UNCHECKED);
  552.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DINDEXEDVS, MF_CHECKED);
  553.                     m_method = D3DINDEXEDVS;
  554.                     break;
  555.                 }
  556.             case ID_OPTIONS_D3DNONINDEXED:
  557.                 {
  558.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DINDEXED, MF_UNCHECKED);
  559.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DNONINDEXED, MF_CHECKED);
  560.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_SOFTWARESKINNING, MF_UNCHECKED);
  561.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DINDEXEDVS, MF_UNCHECKED);
  562.                     m_method = D3DNONINDEXED;
  563.                     break;
  564.                 }
  565.             case ID_OPTIONS_SOFTWARESKINNING:
  566.                 {
  567.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DINDEXED, MF_UNCHECKED);
  568.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DNONINDEXED, MF_UNCHECKED);
  569.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_SOFTWARESKINNING, MF_CHECKED);
  570.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DINDEXEDVS, MF_UNCHECKED);
  571.                     m_method = SOFTWARE;
  572.                     break;
  573.                 }
  574.             }
  575.         }
  576.         break;
  577.     }
  578.  
  579.     return CD3DApplication::MsgProc( hWnd, uMsg, wParam, lParam );
  580. }
  581.  
  582.  
  583.  
  584.  
  585. //-----------------------------------------------------------------------------
  586. // Name: SetProjectionMatrix()
  587. // Desc: 
  588. //-----------------------------------------------------------------------------
  589. HRESULT CMyD3DApplication::SetProjectionMatrix()
  590. {
  591.     D3DXMATRIX mat;
  592.  
  593.     if (m_pdeHead == NULL)
  594.         return S_OK;
  595.  
  596.     FLOAT fAspect = m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height;
  597.     D3DXMatrixPerspectiveFovRH(&mat, 0.25f*3.141592654f, fAspect, m_pdeSelected->fRadius / 64, m_pdeSelected->fRadius * 200);
  598.     HRESULT hr = m_pd3dDevice->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)&mat );
  599.     if (FAILED(hr))
  600.         return hr;
  601.     // Set Projection Matrix for vertex shader
  602.     D3DXMatrixTranspose(&mat, &mat);
  603.     return m_pd3dDevice->SetVertexShaderConstant(2, &mat, 4);
  604. }
  605.