home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Game Programming for Teens / VBGPFT.cdr / DirectX8 / dx8a_sdk.exe / samples / multimedia / direct3d / skinnedmesh / skinnedmesh.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-22  |  16.1 KB  |  506 lines

  1. //-----------------------------------------------------------------------------
  2. // File: SkinnedMesh.cpp
  3. //
  4. // Desc: Example code showing how to use animated models with skinning.
  5. //
  6. // Copyright (c) 1999-2000 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.  
  67.  
  68.  
  69.  
  70. //-----------------------------------------------------------------------------
  71. // Name: ConfirmDevice()
  72. // Desc: Called during device intialization, this code checks the device
  73. //       for some minimum set of capabilities
  74. //-----------------------------------------------------------------------------
  75. HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,
  76.                                           D3DFORMAT Format )
  77. {
  78.     // This sample wants mixed vertex processing rather than hardware
  79.     // vertex processing so it can fallback to sw processing if the 
  80.     // device supports fewer than three matrices when skinning.
  81.     if( dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING )
  82.         return E_FAIL;
  83.  
  84.     return S_OK;
  85. }
  86.  
  87.  
  88.  
  89.  
  90. //-----------------------------------------------------------------------------
  91. // Name: OneTimeSceneInit()
  92. // Desc: Called during initial app startup, this function performs all the
  93. //       permanent initialization.
  94. //-----------------------------------------------------------------------------
  95. HRESULT CMyD3DApplication::OneTimeSceneInit()
  96. {
  97.     // Set cursor to indicate that user can move the object with the mouse
  98. #ifdef _WIN64
  99.     SetClassLongPtr( m_hWnd, GCLP_HCURSOR, (LONG_PTR)LoadCursor( NULL, IDC_SIZEALL ) );
  100. #else
  101.     SetClassLong( m_hWnd, GCL_HCURSOR, (LONG)LoadCursor( NULL, IDC_SIZEALL ) );
  102. #endif
  103.     return S_OK;
  104. }
  105.  
  106.  
  107.  
  108.  
  109. //-----------------------------------------------------------------------------
  110. // Name: FrameMove()
  111. // Desc: Called once per frame, the call is the entry point for animating
  112. //       the scene.
  113. //-----------------------------------------------------------------------------
  114. HRESULT CMyD3DApplication::FrameMove()
  115. {
  116.     SDrawElement *pdeCur;
  117.     SFrame *pframeCur;
  118.  
  119.     pdeCur = m_pdeHead;
  120.     while (pdeCur != NULL)
  121.     {
  122.         pdeCur->fCurTime += m_fElapsedTime * 4800;
  123.         if (pdeCur->fCurTime > 1.0e15f)
  124.             pdeCur->fCurTime = 0;
  125.  
  126.         pframeCur = pdeCur->pframeAnimHead;
  127.         while (pframeCur != NULL)
  128.         {
  129.             pframeCur->SetTime(pdeCur->fCurTime);
  130.             pframeCur = pframeCur->pframeAnimNext;
  131.         }
  132.  
  133.         pdeCur = pdeCur->pdeNext;
  134.     }
  135.     
  136.     return S_OK;
  137. }
  138.  
  139.  
  140.  
  141.  
  142. //-----------------------------------------------------------------------------
  143. // Name: Render()
  144. // Desc: Called once per frame, the call is the entry point for 3d
  145. //       rendering. This function sets up render states, clears the
  146. //       viewport, and renders the scene.
  147. //-----------------------------------------------------------------------------
  148. HRESULT CMyD3DApplication::Render()
  149. {
  150.     // Set up viewing postion from ArcBall
  151.     SDrawElement *pdeCur;
  152.     D3DXMATRIX mat;
  153.     pdeCur = m_pdeHead;
  154.     while (pdeCur != NULL)
  155.     {
  156.         pdeCur->pframeRoot->matRot = *m_ArcBall.GetRotationMatrix();
  157.         pdeCur->pframeRoot->matTrans = *m_ArcBall.GetTranslationMatrix();
  158.         pdeCur = pdeCur->pdeNext;
  159.     }
  160.     
  161.     // Clear the viewport
  162.     m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(89,135,179), 1.0f, 0 );
  163.  
  164.     if (m_pdeHead == NULL)
  165.     {
  166.         return S_OK;
  167.     }
  168.  
  169.     // Begin the scene 
  170.     if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
  171.     {
  172.         UINT cTriangles = 0;
  173.         HRESULT hr;
  174.         SDrawElement *pdeCur;
  175.         D3DXMATRIX matD3D;
  176.         D3DXMATRIX mOut;
  177.         D3DXMATRIX mCur;
  178.         D3DXVECTOR3 vTemp;
  179.         D3DXMATRIX mObject;
  180.         D3DXMATRIX mTrans;
  181.         LPDIRECT3DDEVICE8 m_pDevice = m_pd3dDevice;
  182.  
  183.  
  184.         D3DXMatrixTranslation(&mTrans, 0, 0, -m_pdeSelected->fRadius * 2.8f);
  185.  
  186.         hr = m_pDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&mTrans);
  187.         if(FAILED(hr))
  188.             return hr;
  189.  
  190.         pdeCur = m_pdeHead;
  191.         while (pdeCur != NULL)
  192.         {
  193.             D3DXMatrixTranslation(&mTrans, -pdeCur->vCenter.x, -pdeCur->vCenter.y, -pdeCur->vCenter.z);
  194.             D3DXMatrixIdentity(&mCur);
  195.  
  196.             hr = UpdateFrames(pdeCur->pframeRoot, mCur);
  197.             if (FAILED(hr))
  198.                 return hr;
  199.             hr = DrawFrames(pdeCur->pframeRoot, cTriangles);
  200.             if (FAILED(hr))
  201.                 return hr;
  202.  
  203.             pdeCur = pdeCur->pdeNext;
  204.         }
  205.  
  206.         // Show frame rate
  207.         m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  208.         m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  209.  
  210.         // End the scene.
  211.         m_pd3dDevice->EndScene();
  212.     }
  213.  
  214.     return S_OK;
  215. }
  216.  
  217.  
  218.  
  219.  
  220. //-----------------------------------------------------------------------------
  221. // Name: InitDeviceObjects()
  222. // Desc: Initialize scene objects.
  223. //-----------------------------------------------------------------------------
  224. HRESULT CMyD3DApplication::InitDeviceObjects()
  225. {
  226.     HRESULT hr = S_OK;
  227.  
  228.     // Restore the fonts
  229.     m_pFont->InitDeviceObjects( m_pd3dDevice );
  230.  
  231.     DXUtil_FindMediaFile( m_szPath, _T("tiny.x") );
  232.  
  233.     LoadMeshHierarchy();
  234.  
  235.     if( m_pdeHead != NULL)
  236.         m_ArcBall.SetRadius( m_pdeHead->fRadius );
  237.     
  238.     return S_OK;
  239. }
  240.  
  241.  
  242.  
  243.  
  244. //-----------------------------------------------------------------------------
  245. // Name: RestoreDeviceObjects()
  246. // Desc: Initialize scene objects.
  247. //-----------------------------------------------------------------------------
  248. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  249. {
  250.     // Restore the fonts
  251.     m_pFont->RestoreDeviceObjects();
  252.  
  253.     HRESULT hr = S_OK;
  254.     D3DLIGHT8 light;
  255.  
  256.     m_ArcBall.SetWindow( m_d3dsdBackBuffer.Width, m_d3dsdBackBuffer.Height, 2.0f );
  257.  
  258.     if (m_pdeSelected != NULL)
  259.         SetProjectionMatrix();
  260.  
  261.     m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE );
  262.     m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
  263.     m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
  264.     m_pd3dDevice->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE );
  265.  
  266.     m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
  267.     m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
  268.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR  );
  269.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR  );
  270.  
  271.     m_pd3dDevice->SetRenderState( D3DRS_COLORVERTEX, FALSE );
  272.  
  273.     ZeroMemory( &light, sizeof(light) );
  274.     light.Type = D3DLIGHT_DIRECTIONAL;
  275.  
  276.     light.Diffuse.r = 1.0;
  277.     light.Diffuse.g = 1.0;
  278.     light.Diffuse.b = 1.0;
  279.     light.Specular.r = 0;
  280.     light.Specular.g = 0;
  281.     light.Specular.b = 0;
  282.     light.Ambient.r = 0.25;
  283.     light.Ambient.g = 0.25;
  284.     light.Ambient.b = 0.25;
  285.  
  286.     light.Direction = D3DXVECTOR3( 0.0f, 0.0f, -1.0f);
  287.  
  288.     hr = m_pd3dDevice->SetLight(0, &light );
  289.     if (FAILED(hr))
  290.         return E_FAIL;
  291.  
  292.     hr = m_pd3dDevice->LightEnable(0, TRUE);
  293.     if (FAILED(hr))
  294.         return E_FAIL;
  295.  
  296.     return S_OK;
  297. }
  298.  
  299.  
  300.  
  301.  
  302. //-----------------------------------------------------------------------------
  303. // Name: ReleaseDeviceDependentMeshes()
  304. // Desc: 
  305. //-----------------------------------------------------------------------------
  306. void ReleaseDeviceDependentMeshes(SFrame* pframe)
  307. {
  308.     if (pframe->pmcMesh != NULL)
  309.     {
  310.         for (SMeshContainer* pmcCurr = pframe->pmcMesh; pmcCurr != NULL; pmcCurr = pmcCurr->pmcNext)
  311.         {
  312.             if (pmcCurr->m_pSkinMesh != NULL)
  313.             {
  314.                 GXRELEASE(pmcCurr->pMesh);
  315.                 GXRELEASE(pmcCurr->pMeshHW);
  316.                 GXRELEASE(pmcCurr->pMeshSW);
  317.  
  318.                 pmcCurr->m_Method = NONE;
  319.             }
  320.         }
  321.     }
  322.  
  323.     if (pframe->pframeFirstChild != NULL)
  324.         ReleaseDeviceDependentMeshes(pframe->pframeFirstChild);
  325.  
  326.     if (pframe->pframeSibling != NULL)
  327.         ReleaseDeviceDependentMeshes(pframe->pframeSibling);
  328. }
  329.  
  330.  
  331.  
  332.  
  333. //-----------------------------------------------------------------------------
  334. // Name: InvalidateDeviceObjects()
  335. // Desc: Called when the app is exiting, or the device is being changed,
  336. //       this function deletes any device dependent objects.
  337. //-----------------------------------------------------------------------------
  338. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  339. {
  340.     m_pFont->InvalidateDeviceObjects();
  341.  
  342.  
  343.     for (SDrawElement* pdeCurr = m_pdeHead; pdeCurr != NULL; pdeCurr = pdeCurr->pdeNext)
  344.     {
  345.         ReleaseDeviceDependentMeshes(pdeCurr->pframeRoot);
  346.     }
  347.  
  348.     return S_OK;
  349. }
  350.  
  351.  
  352.  
  353.  
  354. //-----------------------------------------------------------------------------
  355. // Name: DeleteDeviceObjects()
  356. // Desc: Called when the app is exiting, or the device is being changed,
  357. //       this function deletes any device dependent objects.
  358. //-----------------------------------------------------------------------------
  359. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  360. {
  361.     m_pFont->DeleteDeviceObjects();
  362.     
  363.     if( m_pdeSelected == m_pdeHead )
  364.         m_pdeSelected = NULL;
  365.  
  366.     delete m_pdeHead;
  367.     m_pdeHead = NULL;
  368.     
  369.     return S_OK;
  370. }
  371.  
  372.  
  373.  
  374.  
  375. //-----------------------------------------------------------------------------
  376. // Name: FinalCleanup()
  377. // Desc: Called before the app exits, this function gives the app the chance
  378. //       to cleanup after itself.
  379. //-----------------------------------------------------------------------------
  380. HRESULT CMyD3DApplication::FinalCleanup()
  381. {
  382.     SAFE_DELETE( m_pFont );
  383.  
  384.     return S_OK;
  385. }
  386.  
  387.  
  388.  
  389.  
  390. //-----------------------------------------------------------------------------
  391. // Name: MsgProc()
  392. // Desc: Message proc function to handle key and menu input
  393. //-----------------------------------------------------------------------------
  394. LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
  395.                                     LPARAM lParam )
  396. {
  397.     // Pass mouse messages to the ArcBall so it can build internal matrices
  398.     m_ArcBall.HandleMouseMessages( hWnd, uMsg, wParam, lParam );
  399.  
  400.     switch( uMsg )
  401.     {
  402.     case WM_COMMAND:
  403.         if ( 0 == HIWORD(wParam) )
  404.         {
  405.             switch ( LOWORD(wParam) )
  406.             {                
  407.             case ID_FILE_OPENMESHHEIRARCHY:
  408.                 {
  409.                     OPENFILENAME ofn;
  410.                     memset( &ofn, 0, sizeof(ofn) );
  411.                     static TCHAR file[256];
  412.                     static TCHAR szFilepath[256];
  413.                     static TCHAR fileTitle[256];
  414.                     static TCHAR filter[] =
  415.                         TEXT("X files (*.x)\0*.x\0")
  416.                         TEXT("All Files (*.*)\0*.*\0");
  417.                     _tcscpy( file, TEXT(""));
  418.                     _tcscpy( fileTitle, TEXT(""));
  419.                     
  420.                     ofn.lStructSize       = sizeof(ofn);
  421.                     ofn.hwndOwner         = m_hWnd;
  422.                     ofn.hInstance         = NULL;//m_hInstance;
  423.                     ofn.lpstrFilter       = filter;
  424.                     ofn.lpstrCustomFilter = NULL;
  425.                     ofn.nMaxCustFilter    = 0L;
  426.                     ofn.nFilterIndex      = 1L;
  427.                     ofn.lpstrFile         = file;
  428.                     ofn.nMaxFile          = sizeof(file);
  429.                     ofn.lpstrFileTitle    = fileTitle;
  430.                     ofn.nMaxFileTitle     = sizeof(fileTitle);
  431.                     ofn.lpstrInitialDir   = NULL;
  432.                     ofn.nFileOffset       = 0;
  433.                     ofn.nFileExtension    = 0;
  434.                     ofn.lpstrDefExt       = TEXT("*.x");
  435.                     ofn.lCustData         = 0;
  436.                     
  437.                     ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  438.                     if ( ! GetOpenFileName( &ofn) )
  439.                     {
  440.                         TCHAR s[40];
  441.                         DWORD dwErr = CommDlgExtendedError();
  442.                         if ( 0 != dwErr )
  443.                         {
  444.                             wsprintf( s, "GetOpenFileName failed with %x", dwErr );
  445.                             MessageBox( m_hWnd, s, "TexWin", MB_OK | MB_SYSTEMMODAL );
  446.                         }
  447.                         return 0;
  448.                     }
  449.                     lstrcpy(m_szPath, ofn.lpstrFile);
  450.                     HRESULT hr = LoadMeshHierarchy();
  451.                     if (FAILED(hr))
  452.                         MessageBox(NULL, "Could not open file or incorrect file type", "Error loading file", MB_OK);
  453.  
  454.                     return 0;
  455.                 }
  456.             case ID_OPTIONS_D3DINDEXED:
  457.                 {
  458.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DINDEXED, MF_CHECKED);
  459.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DNONINDEXED, MF_UNCHECKED);
  460.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_SOFTWARESKINNING, MF_UNCHECKED);
  461.                     m_method = D3DINDEXED;
  462.                     break;
  463.                 }
  464.             case ID_OPTIONS_D3DNONINDEXED:
  465.                 {
  466.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DINDEXED, MF_UNCHECKED);
  467.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DNONINDEXED, MF_CHECKED);
  468.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_SOFTWARESKINNING, MF_UNCHECKED);
  469.                     m_method = D3DNONINDEXED;
  470.                     break;
  471.                 }
  472.             case ID_OPTIONS_SOFTWARESKINNING:
  473.                 {
  474.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DINDEXED, MF_UNCHECKED);
  475.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DNONINDEXED, MF_UNCHECKED);
  476.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_SOFTWARESKINNING, MF_CHECKED);
  477.                     m_method = SOFTWARE;
  478.                     break;
  479.                 }
  480.             }
  481.         }
  482.         break;
  483.     }
  484.  
  485.     return CD3DApplication::MsgProc( hWnd, uMsg, wParam, lParam );
  486. }
  487.  
  488.  
  489.  
  490.  
  491. //-----------------------------------------------------------------------------
  492. // Name: SetProjectionMatrix()
  493. // Desc: 
  494. //-----------------------------------------------------------------------------
  495. HRESULT CMyD3DApplication::SetProjectionMatrix()
  496. {
  497.     D3DXMATRIX mat;
  498.  
  499.     if (m_pdeHead == NULL)
  500.         return S_OK;
  501.  
  502.     FLOAT fAspect = m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height;
  503.     D3DXMatrixPerspectiveFovRH(&mat, 0.25f*3.141592654f, fAspect, m_pdeSelected->fRadius / 64, m_pdeSelected->fRadius * 200);
  504.     return m_pd3dDevice->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)&mat );
  505. }
  506.