home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / Tutorials / Tut06_Meshes / Meshes.cpp next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  10.6 KB  |  307 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Meshes.cpp
  3. //
  4. // Desc: For advanced geometry, most apps will prefer to load pre-authored
  5. //       meshes from a file. Fortunately, when using meshes, D3DX does most of
  6. //       the work for this, parsing a geometry file and creating vertx buffers
  7. //       (and index buffers) for us. This tutorial shows how to use a D3DXMESH
  8. //       object, including loading it from a file and rendering it. One thing
  9. //       D3DX does not handle for us is the materials and textures for a mesh,
  10. //       so note that we have to handle those manually.
  11. //
  12. //       Note: one advanced (but nice) feature that we don't show here is that
  13. //       when cloning a mesh we can specify the FVF. So, regardless of how the
  14. //       mesh was authored, we can add/remove normals, add more texture
  15. //       coordinate sets (for multi-texturing), etc.
  16. //
  17. // Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
  18. //-----------------------------------------------------------------------------
  19. #include <d3dx8.h>
  20. #include <mmsystem.h>
  21.  
  22.  
  23.  
  24.  
  25. //-----------------------------------------------------------------------------
  26. // Global variables
  27. //-----------------------------------------------------------------------------
  28. LPDIRECT3D8             g_pD3D           = NULL; // Used to create the D3DDevice
  29. LPDIRECT3DDEVICE8       g_pd3dDevice     = NULL; // Our rendering device
  30.  
  31. LPD3DXMESH              g_pMesh          = NULL; // Our mesh object in sysmem
  32. D3DMATERIAL8*           g_pMeshMaterials = NULL; // Materials for our mesh
  33. LPDIRECT3DTEXTURE8*     g_pMeshTextures  = NULL; // Textures for our mesh
  34. DWORD                   g_dwNumMaterials = 0L;   // Number of mesh materials
  35.  
  36.  
  37.  
  38.  
  39. //-----------------------------------------------------------------------------
  40. // Name: InitD3D()
  41. // Desc: Initializes Direct3D
  42. //-----------------------------------------------------------------------------
  43. HRESULT InitD3D( HWND hWnd )
  44. {
  45.     // Create the D3D object.
  46.     if( NULL == ( g_pD3D = Direct3DCreate8( D3D_SDK_VERSION ) ) )
  47.         return E_FAIL;
  48.  
  49.     // Get the current desktop display mode, so we can set up a back
  50.     // buffer of the same format
  51.     D3DDISPLAYMODE d3ddm;
  52.     if( FAILED( g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
  53.         return E_FAIL;
  54.  
  55.     // Set up the structure used to create the D3DDevice. Since we are now
  56.     // using more complex geometry, we will create a device with a zbuffer.
  57.     D3DPRESENT_PARAMETERS d3dpp; 
  58.     ZeroMemory( &d3dpp, sizeof(d3dpp) );
  59.     d3dpp.Windowed = TRUE;
  60.     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
  61.     d3dpp.BackBufferFormat = d3ddm.Format;
  62.     d3dpp.EnableAutoDepthStencil = TRUE;
  63.     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
  64.  
  65.     // Create the D3DDevice
  66.     if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
  67.                                       D3DCREATE_SOFTWARE_VERTEXPROCESSING,
  68.                                       &d3dpp, &g_pd3dDevice ) ) )
  69.     {
  70.         return E_FAIL;
  71.     }
  72.  
  73.     // Turn on the zbuffer
  74.     g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
  75.  
  76.     // Turn on ambient lighting 
  77.     g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );
  78.  
  79.     return S_OK;
  80. }
  81.  
  82.  
  83.  
  84.  
  85. //-----------------------------------------------------------------------------
  86. // Name: InitGeometry()
  87. // Desc: Load the mesh and build the material and texture arrays
  88. //-----------------------------------------------------------------------------
  89. HRESULT InitGeometry()
  90. {
  91.     LPD3DXBUFFER pD3DXMtrlBuffer;
  92.  
  93.     // Load the mesh from the specified file
  94.     if( FAILED( D3DXLoadMeshFromX( "Tiger.x", D3DXMESH_SYSTEMMEM, 
  95.                                    g_pd3dDevice, NULL, 
  96.                                    &pD3DXMtrlBuffer, &g_dwNumMaterials, 
  97.                                    &g_pMesh ) ) )
  98.     {
  99.         return E_FAIL;
  100.     }
  101.  
  102.     // We need to extract the material properties and texture names from the 
  103.     // pD3DXMtrlBuffer
  104.     D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
  105.     g_pMeshMaterials = new D3DMATERIAL8[g_dwNumMaterials];
  106.     g_pMeshTextures  = new LPDIRECT3DTEXTURE8[g_dwNumMaterials];
  107.  
  108.     for( DWORD i=0; i<g_dwNumMaterials; i++ )
  109.     {
  110.         // Copy the material
  111.         g_pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
  112.  
  113.         // Set the ambient color for the material (D3DX does not do this)
  114.         g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse;
  115.      
  116.         // Create the texture
  117.         if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, 
  118.                                                d3dxMaterials[i].pTextureFilename, 
  119.                                                &g_pMeshTextures[i] ) ) )
  120.         {
  121.             g_pMeshTextures[i] = NULL;
  122.         }
  123.     }
  124.  
  125.     // Done with the material buffer
  126.     pD3DXMtrlBuffer->Release();
  127.  
  128.     return S_OK;
  129. }
  130.  
  131.  
  132.  
  133.  
  134. //-----------------------------------------------------------------------------
  135. // Name: Cleanup()
  136. // Desc: Releases all previously initialized objects
  137. //-----------------------------------------------------------------------------
  138. VOID Cleanup()
  139. {
  140.     if( g_pMeshMaterials != NULL ) 
  141.         delete[] g_pMeshMaterials;
  142.  
  143.     if( g_pMeshTextures )
  144.     {
  145.         for( DWORD i = 0; i < g_dwNumMaterials; i++ )
  146.         {
  147.             if( g_pMeshTextures[i] )
  148.                 g_pMeshTextures[i]->Release();
  149.         }
  150.         delete[] g_pMeshTextures;
  151.     }
  152.     if( g_pMesh != NULL )
  153.         g_pMesh->Release();
  154.     
  155.     if( g_pd3dDevice != NULL )
  156.         g_pd3dDevice->Release();
  157.  
  158.     if( g_pD3D != NULL )
  159.         g_pD3D->Release();
  160. }
  161.  
  162.  
  163.  
  164. //-----------------------------------------------------------------------------
  165. // Name: SetupMatrices()
  166. // Desc: Sets up the world, view, and projection transform matrices.
  167. //-----------------------------------------------------------------------------
  168. VOID SetupMatrices()
  169. {
  170.     // For our world matrix, we will just leave it as the identity
  171.     D3DXMATRIX matWorld;
  172.     D3DXMatrixRotationY( &matWorld, timeGetTime()/1000.0f );
  173.     g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  174.  
  175.     // Set up our view matrix. A view matrix can be defined given an eye point,
  176.     // a point to lookat, and a direction for which way is up. Here, we set the
  177.     // eye five units back along the z-axis and up three units, look at the 
  178.     // origin, and define "up" to be in the y-direction.
  179.     D3DXMATRIX matView;
  180.     D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3( 0.0f, 3.0f,-5.0f ), 
  181.                                   &D3DXVECTOR3( 0.0f, 0.0f, 0.0f ), 
  182.                                   &D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
  183.     g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  184.  
  185.     // For the projection matrix, we set up a perspective transform (which
  186.     // transforms geometry from 3D view space to 2D viewport space, with
  187.     // a perspective divide making objects smaller in the distance). To build
  188.     // a perpsective transform, we need the field of view (1/4 pi is common),
  189.     // the aspect ratio, and the near and far clipping planes (which define at
  190.     // what distances geometry should be no longer be rendered).
  191.     D3DXMATRIX matProj;
  192.     D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
  193.     g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
  194. }
  195.  
  196.  
  197.  
  198.  
  199. //-----------------------------------------------------------------------------
  200. // Name: Render()
  201. // Desc: Draws the scene
  202. //-----------------------------------------------------------------------------
  203. VOID Render()
  204. {
  205.     // Clear the backbuffer and the zbuffer
  206.     g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 
  207.                          D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
  208.     
  209.     // Begin the scene
  210.     g_pd3dDevice->BeginScene();
  211.  
  212.     // Setup the world, view, and projection matrices
  213.     SetupMatrices();
  214.  
  215.     // Meshes are divided into subsets, one for each material. Render them in
  216.     // a loop
  217.     for( DWORD i=0; i<g_dwNumMaterials; i++ )
  218.     {
  219.         // Set the material and texture for this subset
  220.         g_pd3dDevice->SetMaterial( &g_pMeshMaterials[i] );
  221.         g_pd3dDevice->SetTexture( 0, g_pMeshTextures[i] );
  222.         
  223.         // Draw the mesh subset
  224.         g_pMesh->DrawSubset( i );
  225.     }
  226.  
  227.     // End the scene
  228.     g_pd3dDevice->EndScene();
  229.     
  230.     // Present the backbuffer contents to the display
  231.     g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
  232. }
  233.  
  234.  
  235.  
  236.  
  237. //-----------------------------------------------------------------------------
  238. // Name: MsgProc()
  239. // Desc: The window's message handler
  240. //-----------------------------------------------------------------------------
  241. LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
  242. {
  243.     switch( msg )
  244.     {
  245.         case WM_DESTROY:
  246.             PostQuitMessage( 0 );
  247.             return 0;
  248.     }
  249.  
  250.     return DefWindowProc( hWnd, msg, wParam, lParam );
  251. }
  252.  
  253.  
  254.  
  255.  
  256. //-----------------------------------------------------------------------------
  257. // Name: WinMain()
  258. // Desc: The application's entry point
  259. //-----------------------------------------------------------------------------
  260. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  261. {
  262.     // Register the window class
  263.     WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, 
  264.                       GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
  265.                       "D3D Tutorial", NULL };
  266.     RegisterClassEx( &wc );
  267.  
  268.     // Create the application's window
  269.     HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 06: Meshes", 
  270.                               WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
  271.                               GetDesktopWindow(), NULL, wc.hInstance, NULL );
  272.  
  273.     // Initialize Direct3D
  274.     if( SUCCEEDED( InitD3D( hWnd ) ) )
  275.     { 
  276.         // Create the scene geometry
  277.         if( SUCCEEDED( InitGeometry() ) )
  278.         {
  279.             // Show the window
  280.             ShowWindow( hWnd, SW_SHOWDEFAULT );
  281.             UpdateWindow( hWnd );
  282.  
  283.             // Enter the message loop
  284.             MSG msg; 
  285.             ZeroMemory( &msg, sizeof(msg) );
  286.             while( msg.message!=WM_QUIT )
  287.             {
  288.                 if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
  289.                 {
  290.                     TranslateMessage( &msg );
  291.                     DispatchMessage( &msg );
  292.                 }
  293.                 else
  294.                     Render();
  295.             }
  296.         }
  297.     }
  298.  
  299.     // Clean up everything and exit the app
  300.     Cleanup();
  301.     UnregisterClass( "D3D Tutorial", wc.hInstance );
  302.     return 0;
  303. }
  304.  
  305.  
  306.  
  307.