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

  1. //-----------------------------------------------------------------------------
  2. // File: ProgressiveMesh.cpp
  3. //
  4. // Desc: Sample of creating progressive meshes in D3D
  5. //
  6. // Copyright (c) 1998-2000 Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #include <stdio.h>
  10. #include <windows.h>
  11. #include <commdlg.h>
  12. #include <D3DX8.h>
  13. #include "D3DApp.h"
  14. #include "D3DFont.h"
  15. #include "D3DUtil.h"
  16. #include "DXUtil.h"
  17. #include "resource.h"
  18.  
  19.  
  20.  
  21.  
  22. //-----------------------------------------------------------------------------
  23. // Name: class CMyD3DApplication
  24. // Desc: Main class to run this application. Most functionality is inherited
  25. //       from the CD3DApplication base class.
  26. //-----------------------------------------------------------------------------
  27. class CMyD3DApplication : public CD3DApplication
  28. {
  29.     TCHAR               m_strInitialDir[512];
  30.     TCHAR               m_strMeshFilename[512]; // Filename of mesh
  31.     LPD3DXPMESH         m_pPMeshSysMem;         // Sysmem version of pmesh, lives through resize's
  32.     LPD3DXPMESH         m_pPMesh;          // Local version of pmesh, rebuilt on resize
  33.  
  34.     D3DMATERIAL8*       m_mtrlMeshMaterials;
  35.     LPDIRECT3DTEXTURE8* m_pMeshTextures;        // Array of textures, entries are NULL if no texture specified
  36.     DWORD               m_dwNumMaterials;       // Number of materials
  37.     LPD3DXBUFFER        m_pAdjacencyBuffer;     // Contains the adjaceny info loaded with the mesh
  38.  
  39.     CD3DArcBall         m_ArcBall;              // Mouse rotation utility
  40.     D3DXVECTOR3         m_vObjectCenter;        // Center of bounding sphere of object
  41.     FLOAT               m_fObjectRadius;        // Radius of bounding sphere of object
  42.  
  43.     CD3DFont*           m_pFont;                // Font for displaying help
  44.     BOOL                m_bDisplayHelp;
  45.  
  46. public:
  47.     HRESULT OneTimeSceneInit();
  48.     HRESULT InitDeviceObjects();
  49.     HRESULT RestoreDeviceObjects();
  50.     HRESULT InvalidateDeviceObjects();
  51.     HRESULT DeleteDeviceObjects();
  52.     HRESULT Render();
  53.     HRESULT FrameMove();
  54.     HRESULT FinalCleanup();
  55.     LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  56.  
  57.     CMyD3DApplication();
  58. };
  59.  
  60.  
  61.  
  62.  
  63. //-----------------------------------------------------------------------------
  64. // Name: WinMain()
  65. // Desc: Entry point to the program. Initializes everything, and goes into a
  66. //       message-processing loop. Idle time is used to render the scene.
  67. //-----------------------------------------------------------------------------
  68. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  69. {
  70.     CMyD3DApplication d3dApp;
  71.  
  72.     if( FAILED( d3dApp.Create( hInst ) ) )
  73.         return 0;
  74.  
  75.     return d3dApp.Run();
  76. }
  77.  
  78.  
  79.  
  80.  
  81. //-----------------------------------------------------------------------------
  82. // Name: CMyD3DApplication()
  83. // Desc: Constructor
  84. //-----------------------------------------------------------------------------
  85. CMyD3DApplication::CMyD3DApplication()
  86. {
  87.     // Override base class members
  88.     m_strWindowTitle    = _T("ProgressiveMesh: Using Progressive Meshes in D3D");
  89.     m_bUseDepthBuffer   = TRUE;
  90.     m_bShowCursorWhenFullscreen = TRUE;
  91.  
  92.     // Initialize member variables
  93.     _tcscpy( m_strInitialDir, DXUtil_GetDXSDKMediaPath() );
  94.     _tcscpy( m_strMeshFilename, _T("Tiger.x") );
  95.  
  96.     m_pPMesh             = NULL;
  97.     m_pAdjacencyBuffer   = NULL;
  98.  
  99.     m_dwNumMaterials     = 0L;
  100.     m_mtrlMeshMaterials  = NULL;
  101.     m_pMeshTextures      = NULL;
  102.  
  103.     m_pFont              = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  104.     m_bDisplayHelp       = FALSE;
  105. }
  106.  
  107.  
  108.  
  109.  
  110. //-----------------------------------------------------------------------------
  111. // Name: OneTimeSceneInit()
  112. // Desc: Called during initial app startup, this function performs all the
  113. //       permanent initialization.
  114. //-----------------------------------------------------------------------------
  115. HRESULT CMyD3DApplication::OneTimeSceneInit()
  116. {
  117.     // Set cursor to indicate that user can move the object with the mouse
  118. #ifdef _WIN64
  119.     SetClassLongPtr( m_hWnd, GCLP_HCURSOR, (LONG_PTR)LoadCursor( NULL, IDC_SIZEALL ) );
  120. #else
  121.     SetClassLong( m_hWnd, GCL_HCURSOR, (LONG)LoadCursor( NULL, IDC_SIZEALL ) );
  122. #endif
  123.     return S_OK;
  124. }
  125.  
  126.  
  127.  
  128.  
  129. //-----------------------------------------------------------------------------
  130. // Name: FrameMove()
  131. // Desc: Called once per frame, the call is the entry point for animating
  132. //       the scene.
  133. //-----------------------------------------------------------------------------
  134. HRESULT CMyD3DApplication::FrameMove()
  135. {
  136.     // Setup world matrix
  137.     D3DXMATRIX matWorld;
  138.     D3DXMATRIX matRotationInverse;
  139.     D3DXMatrixTranslation( &matWorld, -m_vObjectCenter.x,
  140.                                       -m_vObjectCenter.y,
  141.                                       -m_vObjectCenter.z );
  142.     D3DXMatrixInverse( &matRotationInverse, NULL, m_ArcBall.GetRotationMatrix() );
  143.     D3DXMatrixMultiply( &matWorld, &matWorld, &matRotationInverse );
  144.     D3DXMatrixMultiply( &matWorld, &matWorld, m_ArcBall.GetTranslationMatrix() );
  145.     m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  146.  
  147.     // Set up view matrix
  148.     D3DXMATRIX matView;
  149.     D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3( 0, 0,-3*m_fObjectRadius ),
  150.                                   &D3DXVECTOR3( 0, 0, 0 ),
  151.                                   &D3DXVECTOR3( 0, 1, 0 ) );
  152.     m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  153.  
  154.     return S_OK;
  155. }
  156.  
  157.  
  158.  
  159.  
  160. //-----------------------------------------------------------------------------
  161. // Name: Render()
  162. // Desc: Called once per frame, the call is the entry point for 3d
  163. //       rendering. This function sets up render states, clears the
  164. //       viewport, and renders the scene.
  165. //-----------------------------------------------------------------------------
  166. HRESULT CMyD3DApplication::Render()
  167. {
  168.     // Clear the backbuffer
  169.     m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
  170.                          0x000000ff, 1.0f, 0x00000000 );
  171.  
  172.     // Begin scene rendering
  173.     if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
  174.     {
  175.         if( m_pPMesh )
  176.         {
  177.             // Set and draw each of the materials in the mesh
  178.             for( DWORD i=0; i<m_dwNumMaterials; i++ )
  179.             {
  180.                 m_pd3dDevice->SetMaterial( &m_mtrlMeshMaterials[i] );
  181.                 m_pd3dDevice->SetTexture( 0, m_pMeshTextures[i] );
  182.                 m_pPMesh->DrawSubset( i );
  183.             }
  184.         }
  185.  
  186.  
  187.         // Output statistics
  188.         m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  189.         m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  190.         TCHAR strBuffer[512];
  191.         sprintf( strBuffer, _T("Num Vertices = %ld"),
  192.                  m_pPMesh ? m_pPMesh->GetNumVertices() : 0L );
  193.         m_pFont->DrawText( 2, 40, 0xffffff00, strBuffer );
  194.  
  195.         // Output text
  196.         if( m_bDisplayHelp )
  197.         {
  198.             m_pFont->DrawText(  2, 60, 0xffffffff, _T("<F1>\n\n")
  199.                                                    _T("<Up>\n")
  200.                                                    _T("<Down>\n\n")
  201.                                                    _T("<PgUp>\n")
  202.                                                    _T("<PgDn>\n\n")
  203.                                                    _T("<Home>\n")
  204.                                                    _T("<End>"), 0L );
  205.             m_pFont->DrawText( 70, 60, 0xffffffff, _T("Toggle help\n\n")
  206.                                                    _T("Add one vertex\n")
  207.                                                    _T("Subtract one vertex\n\n")
  208.                                                    _T("Add 100 vertices\n")
  209.                                                    _T("Subtract 100 vertices\n\n")
  210.                                                    _T("Max vertices\n")
  211.                                                    _T("Min vertices") );
  212.         }
  213.         else
  214.         {
  215.             m_pFont->DrawText(  2, 60, 0xffffffff, _T("<F1>\n") );
  216.             m_pFont->DrawText( 70, 60, 0xffffffff, _T("Toggle help\n") );
  217.         }
  218.  
  219.         // End the scene rendering
  220.         m_pd3dDevice->EndScene();
  221.     }
  222.  
  223.     return S_OK;
  224. }
  225.  
  226.  
  227.  
  228.  
  229. //-----------------------------------------------------------------------------
  230. // Name: InitDeviceObjects()
  231. // Desc: Initialize scene objects.
  232. //-----------------------------------------------------------------------------
  233. HRESULT CMyD3DApplication::InitDeviceObjects()
  234. {
  235.     // Initialize the font
  236.     m_pFont->InitDeviceObjects( m_pd3dDevice );
  237.  
  238.     // Load mesh
  239.     LPDIRECT3DVERTEXBUFFER8 pVertexBuffer = NULL;
  240.     LPD3DXMESH   pMesh;
  241.     LPD3DXMESH   pTempMesh;
  242.     LPD3DXBUFFER pD3DXMtrlBuffer;
  243.     BYTE*        pVertices;
  244.     TCHAR        strMediaPath[512];
  245.     HRESULT      hr;
  246.  
  247.     // Find the path to the mesh
  248.     if( FAILED( DXUtil_FindMediaFile( strMediaPath, m_strMeshFilename ) ) )
  249.         return D3DAPPERR_MEDIANOTFOUND;
  250.  
  251.     // Load the mesh from the specified file
  252.     if( FAILED( hr = D3DXLoadMeshFromX( strMediaPath, D3DXMESH_MANAGED, m_pd3dDevice,
  253.                                         &m_pAdjacencyBuffer, &pD3DXMtrlBuffer,
  254.                                         &m_dwNumMaterials, &pMesh ) ) )
  255.         return hr;
  256.  
  257.     if( FAILED( hr = D3DXValidMesh( pMesh, (DWORD*)m_pAdjacencyBuffer->GetBufferPointer() ) ) )
  258.     {
  259.         SAFE_RELEASE( m_pAdjacencyBuffer );
  260.         SAFE_RELEASE( pD3DXMtrlBuffer );
  261.         SAFE_RELEASE( pMesh );
  262.         m_dwNumMaterials = 0;
  263.         return E_FAIL;
  264.     }
  265.  
  266.     // Allocate a material/texture arrays
  267.     D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
  268.     m_mtrlMeshMaterials = new D3DMATERIAL8[m_dwNumMaterials];
  269.     m_pMeshTextures     = new LPDIRECT3DTEXTURE8[m_dwNumMaterials];
  270.  
  271.     // Copy the materials and load the textures
  272.     for( DWORD i=0; i<m_dwNumMaterials; i++ )
  273.     {
  274.         m_mtrlMeshMaterials[i] = d3dxMaterials[i].MatD3D;
  275.         m_mtrlMeshMaterials[i].Ambient = m_mtrlMeshMaterials[i].Diffuse;
  276.  
  277.         // Find the path to the texture and create that texture
  278.         DXUtil_FindMediaFile( strMediaPath, d3dxMaterials[i].pTextureFilename );
  279.         if( FAILED( D3DXCreateTextureFromFile( m_pd3dDevice, strMediaPath, 
  280.                                                &m_pMeshTextures[i] ) ) )
  281.             m_pMeshTextures[i] = NULL;
  282.     }
  283.     pD3DXMtrlBuffer->Release();
  284.  
  285.     // Lock the vertex buffer, to generate a simple bounding sphere
  286.     hr = pMesh->GetVertexBuffer( &pVertexBuffer );
  287.     if( FAILED(hr) )
  288.     {
  289.         pMesh->Release();
  290.         return hr;
  291.     }
  292.  
  293.     hr = pVertexBuffer->Lock( 0, 0, &pVertices, D3DLOCK_NOSYSLOCK );
  294.     if( FAILED(hr) )
  295.     {
  296.         pVertexBuffer->Release();
  297.         pMesh->Release();
  298.         return hr;
  299.     }
  300.  
  301.     hr = D3DXComputeBoundingSphere( pVertices, pMesh->GetNumVertices(),
  302.                                     pMesh->GetFVF(),
  303.                                     &m_vObjectCenter, &m_fObjectRadius );
  304.     pVertexBuffer->Unlock();
  305.     pVertexBuffer->Release();
  306.  
  307.     if( FAILED(hr) || m_dwNumMaterials == 0 )
  308.     {
  309.         pMesh->Release();
  310.         return hr;
  311.     }
  312.  
  313.     if (pMesh->GetFVF() != (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1))
  314.     {
  315.         hr = pMesh->CloneMeshFVF( D3DXMESH_SYSTEMMEM, D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1, 
  316.                                             m_pd3dDevice, &pTempMesh );
  317.         if (FAILED(hr))
  318.             return hr;
  319.  
  320.         if ( !(pMesh->GetFVF() & D3DFVF_NORMAL))
  321.         {
  322.             D3DXComputeNormals( pTempMesh );
  323.         }
  324.  
  325.         pMesh->Release();
  326.         pMesh = pTempMesh;
  327.     }
  328.  
  329.     hr = D3DXGeneratePMesh( pMesh, (DWORD*)m_pAdjacencyBuffer->GetBufferPointer(),
  330.                             NULL, NULL, 1, D3DXMESHSIMP_VERTEX, &m_pPMesh);
  331.     pMesh->Release();
  332.     if( FAILED(hr) )
  333.         return hr;
  334.  
  335.     m_pPMesh->SetNumVertices( 0xffffffff );
  336.  
  337.     return S_OK;
  338. }
  339.  
  340.  
  341.  
  342.  
  343. //-----------------------------------------------------------------------------
  344. // Name: RestoreDeviceObjects()
  345. // Desc: Initialize scene objects.
  346. //-----------------------------------------------------------------------------
  347. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  348. {
  349.     m_pFont->RestoreDeviceObjects();
  350.  
  351.     // Setup render state
  352.     m_pd3dDevice->SetRenderState( D3DRS_LIGHTING,     TRUE );
  353.     m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE );
  354.     m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,      TRUE );
  355.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  356.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  357.  
  358.     // Setup the light
  359.     D3DLIGHT8 light;
  360.     D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, 0.0f, -0.5f, 1.0f );
  361.     m_pd3dDevice->SetLight( 0, &light );
  362.     m_pd3dDevice->LightEnable( 0, TRUE );
  363.     m_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00333333 );
  364.  
  365.     // Set the arcball parameters
  366.     m_ArcBall.SetWindow( m_d3dsdBackBuffer.Width, m_d3dsdBackBuffer.Height,
  367.                          0.85f );
  368.     m_ArcBall.SetRadius( m_fObjectRadius );
  369.  
  370.     // Set the projection matrix
  371.     D3DXMATRIX matProj;
  372.     FLOAT      fAspect = m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height;
  373.     D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, m_fObjectRadius/64.0f,
  374.                                 m_fObjectRadius*200.0f);
  375.     m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
  376.  
  377.     return S_OK;
  378. }
  379.  
  380.  
  381.  
  382.  
  383. //-----------------------------------------------------------------------------
  384. // Name: InvalidateDeviceObjects()
  385. // Desc: 
  386. //-----------------------------------------------------------------------------
  387. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  388. {
  389.     m_pFont->InvalidateDeviceObjects();
  390.  
  391.     return S_OK;
  392. }
  393.  
  394.  
  395.  
  396.  
  397. //-----------------------------------------------------------------------------
  398. // Name: DeleteDeviceObjects()
  399. // Desc: Called when the app is exiting, or the device is being changed,
  400. //       this function deletes any device dependent objects.
  401. //-----------------------------------------------------------------------------
  402. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  403. {
  404.     m_pFont->DeleteDeviceObjects();
  405.  
  406.     if( m_pMeshTextures != NULL)
  407.     {
  408.         for( UINT i=0; i<m_dwNumMaterials; i++ )
  409.             SAFE_RELEASE( m_pMeshTextures[i] );
  410.     }
  411.     SAFE_DELETE_ARRAY( m_pMeshTextures );
  412.     SAFE_RELEASE( m_pPMesh );
  413.     SAFE_RELEASE( m_pAdjacencyBuffer );
  414.     SAFE_DELETE_ARRAY( m_mtrlMeshMaterials );
  415.     m_dwNumMaterials = 0L;
  416.  
  417.     return S_OK;
  418. }
  419.  
  420.  
  421.  
  422.  
  423. //-----------------------------------------------------------------------------
  424. // Name: FinalCleanup()
  425. // Desc: Called during initial app startup, this function performs all the
  426. //       permanent initialization.
  427. //-----------------------------------------------------------------------------
  428. HRESULT CMyD3DApplication::FinalCleanup()
  429. {
  430.     SAFE_DELETE( m_pFont );
  431.  
  432.     return S_OK;
  433. }
  434.  
  435.  
  436.  
  437.  
  438. //-----------------------------------------------------------------------------
  439. // Name: MsgProc()
  440. // Desc: Message proc function to handle key and menu input
  441. //-----------------------------------------------------------------------------
  442. LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
  443.                                     LPARAM lParam )
  444. {
  445.     // Pass mouse messages to the ArcBall so it can build internal matrices
  446.     m_ArcBall.HandleMouseMessages( hWnd, uMsg, wParam, lParam );
  447.  
  448.     // Trap the context menu
  449.     if( uMsg == WM_CONTEXTMENU )
  450.         return 0;
  451.  
  452.     if( uMsg == WM_COMMAND )
  453.     {
  454.         // Handle the about command (which displays help)
  455.         if( LOWORD(wParam) == IDM_TOGGLEHELP )
  456.         {
  457.             m_bDisplayHelp = !m_bDisplayHelp;
  458.             return 0;
  459.         }
  460.  
  461.         // Handle the open file command
  462.         if( m_bWindowed && LOWORD(wParam) == IDM_OPENFILE )
  463.         {
  464.             TCHAR g_strFilename[512]   = _T("");
  465.  
  466.             // Display the OpenFileName dialog. Then, try to load the specified file
  467.             OPENFILENAME ofn = { sizeof(OPENFILENAME), NULL, NULL,
  468.                                 _T(".X Files (.x)\0*.x\0\0"), 
  469.                                 NULL, 0, 1, m_strMeshFilename, 512, g_strFilename, 512, 
  470.                                 m_strInitialDir, _T("Open Mesh File"), 
  471.                                 OFN_FILEMUSTEXIST, 0, 1, NULL, 0, NULL, NULL };
  472.  
  473.             if( TRUE == GetOpenFileName( &ofn ) )
  474.             {
  475.                 _tcscpy( m_strInitialDir, m_strMeshFilename );
  476.                 TCHAR* pLastSlash =  _tcsrchr( m_strInitialDir, _T('\\') );
  477.                 if( pLastSlash )
  478.                     *pLastSlash = 0;
  479.                 SetCurrentDirectory( m_strInitialDir );
  480.  
  481.                 // Destroy and recreate everything
  482.                 InvalidateDeviceObjects();
  483.                 DeleteDeviceObjects();
  484.                 
  485.                 if( FAILED( InitDeviceObjects() ) )
  486.                 {
  487.                     MessageBox( m_hWnd, _T("Error loading mesh: mesh may not\n")
  488.                                         _T("be valid. See debug output for\n")
  489.                                         _T("more information.\n\nPlease select ") 
  490.                                         _T("a different .x file."), 
  491.                                         _T("ProgressiveMesh"), MB_ICONERROR|MB_OK );
  492.                 }
  493.  
  494.                 RestoreDeviceObjects();
  495.             }
  496.         }
  497.     }
  498.  
  499.     if( uMsg == WM_KEYDOWN )
  500.     {
  501.         if( m_pPMesh )
  502.         {
  503.             DWORD dwNumMeshVertices = m_pPMesh->GetNumVertices();
  504.  
  505.             if( wParam == VK_UP )
  506.             {
  507.                 // Sometimes it is necessary to add more than one
  508.                 // vertex when increasing the resolution of a 
  509.                 // progressive mesh, so keep adding until the 
  510.                 // vertex count increases.
  511.                 for( int i = 1; i <= 8; i++ )
  512.                 {
  513.                     m_pPMesh->SetNumVertices( dwNumMeshVertices+i );
  514.                     if( m_pPMesh->GetNumVertices() == dwNumMeshVertices+i )
  515.                         break;
  516.                 }
  517.             }
  518.             else if( wParam == VK_DOWN )
  519.                 m_pPMesh->SetNumVertices( dwNumMeshVertices-1 );
  520.             else if( wParam == VK_PRIOR )
  521.                 m_pPMesh->SetNumVertices( dwNumMeshVertices+100 );
  522.             else if( wParam == VK_NEXT )
  523.                 m_pPMesh->SetNumVertices( dwNumMeshVertices<=100 ? 1 : dwNumMeshVertices-100 );
  524.             else if( wParam == VK_HOME )
  525.                 m_pPMesh->SetNumVertices( 0xffffffff );
  526.             else if( wParam == VK_END )
  527.                 m_pPMesh->SetNumVertices( 1 );
  528.         }
  529.     }
  530.  
  531.     return CD3DApplication::MsgProc( hWnd, uMsg, wParam, lParam );
  532. }
  533.  
  534.  
  535.  
  536.