0001: //-----------------------------------------------------------------------------
0002: // File: sample.cpp
0003: //
0004: // Desc: DirectX window application created by the DirectX AppWizard
0005: //-----------------------------------------------------------------------------
0006: #define STRICT
0007: #include <windows.h>
0008: #include <basetsd.h>
0009: #include <math.h>
0010: #include <stdio.h>
0011: #include <D3DX8.h>
0012: #include <DXErr8.h>
0013: #include <tchar.h>
0014: #include "D3DApp.h"
0015: #include "D3DFont.h"
0016: #include "D3DFile.h"
0017: #include "D3DUtil.h"
0018: #include "DXUtil.h"
0019: #include "resource.h"
0020: #include "sample.h"
0021: 
0022: 
0023: 
0024: //-----------------------------------------------------------------------------
0025: // Global access to the app (needed for the global WndProc())
0026: //-----------------------------------------------------------------------------
0027: CMyD3DApplication* g_pApp  = NULL;
0028: HINSTANCE          g_hInst = NULL;
0029: 
0030: 
0031: 
0032: 
0033: //-----------------------------------------------------------------------------
0034: // Name: WinMain()
0035: // Desc: Entry point to the program. Initializes everything, and goes into a
0036: //       message-processing loop. Idle time is used to render the scene.
0037: //-----------------------------------------------------------------------------
0038: INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
0039: {
0040:     CMyD3DApplication d3dApp;
0041: 
0042:     g_pApp  = &d3dApp;
0043:     g_hInst = hInst;
0044: 
0045:     if( FAILED( d3dApp.Create( hInst ) ) )
0046:         return 0;
0047: 
0048:     return d3dApp.Run();
0049: }
0050: 
0051: 
0052: 
0053: 
0054: //-----------------------------------------------------------------------------
0055: // Name: CMyD3DApplication()
0056: // Desc: Application constructor. Sets attributes for the app.
0057: //-----------------------------------------------------------------------------
0058: CMyD3DApplication::CMyD3DApplication()
0059: {
0060:     m_dwCreationWidth           = 500;
0061:     m_dwCreationHeight          = 375;
0062:     m_strWindowTitle            = TEXT( "sample" );
0063:     m_bUseDepthBuffer           = TRUE;
0064: 
0065:     // Create a D3D font using d3dfont.cpp
0066:     m_pFont                     = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
0067:     m_bLoadingApp               = TRUE;
0068:     m_pD3DXMesh                 = NULL;
0069: 
0070:     ZeroMemory( &m_UserInput, sizeof(m_UserInput) );
0071:     m_fWorldRotX                = 0.0f;
0072:     m_fWorldRotY                = 0.0f;
0073: 
0074:     // Read settings from registry
0075:     ReadSettings();
0076: }
0077: 
0078: 
0079: 
0080: 
0081: //-----------------------------------------------------------------------------
0082: // Name: OneTimeSceneInit()
0083: // Desc: Called during initial app startup, this function performs all the
0084: //       permanent initialization.
0085: //-----------------------------------------------------------------------------
0086: HRESULT CMyD3DApplication::OneTimeSceneInit()
0087: {
0088:     // TODO: perform one time initialization
0089: 
0090:     // Drawing loading status message until app finishes loading
0091:     SendMessage( m_hWnd, WM_PAINT, 0, 0 );
0092: 
0093:     m_bLoadingApp = FALSE;
0094: 
0095:     return S_OK;
0096: }
0097: 
0098: 
0099: 
0100: 
0101: //-----------------------------------------------------------------------------
0102: // Name: ReadSettings()
0103: // Desc: Read the app settings from the registry
0104: //-----------------------------------------------------------------------------
0105: VOID CMyD3DApplication::ReadSettings()
0106: {
0107:     HKEY hkey;
0108:     if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, DXAPP_KEY, 
0109:         0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) )
0110:     {
0111:         // TODO: change as needed
0112: 
0113:         // Read the stored window width/height.  This is just an example,
0114:         // of how to use DXUtil_Read*() functions.
0115:         DXUtil_ReadIntRegKey( hkey, TEXT("Width"), &m_dwCreationWidth, m_dwCreationWidth );
0116:         DXUtil_ReadIntRegKey( hkey, TEXT("Height"), &m_dwCreationHeight, m_dwCreationHeight );
0117: 
0118:         RegCloseKey( hkey );
0119:     }
0120: }
0121: 
0122: 
0123: 
0124: 
0125: //-----------------------------------------------------------------------------
0126: // Name: WriteSettings()
0127: // Desc: Write the app settings to the registry
0128: //-----------------------------------------------------------------------------
0129: VOID CMyD3DApplication::WriteSettings()
0130: {
0131:     HKEY hkey;
0132:     DWORD dwType = REG_DWORD;
0133:     DWORD dwLength = sizeof(DWORD);
0134: 
0135:     if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, DXAPP_KEY, 
0136:         0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) )
0137:     {
0138:         // TODO: change as needed
0139: 
0140:         // Write the window width/height.  This is just an example,
0141:         // of how to use DXUtil_Write*() functions.
0142:         DXUtil_WriteIntRegKey( hkey, TEXT("Width"), m_rcWindowClient.right );
0143:         DXUtil_WriteIntRegKey( hkey, TEXT("Height"), m_rcWindowClient.bottom );
0144: 
0145:         RegCloseKey( hkey );
0146:     }
0147: }
0148: 
0149: 
0150: 
0151: 
0152: 
0153: //-----------------------------------------------------------------------------
0154: // Name: ConfirmDevice()
0155: // Desc: Called during device initialization, this code checks the display device
0156: //       for some minimum set of capabilities
0157: //-----------------------------------------------------------------------------
0158: HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,
0159:                                           D3DFORMAT Format )
0160: {
0161:     BOOL bCapsAcceptable;
0162: 
0163:     // TODO: Perform checks to see if these display caps are acceptable.
0164:     bCapsAcceptable = TRUE;
0165: 
0166:     if( bCapsAcceptable )         
0167:         return S_OK;
0168:     else
0169:         return E_FAIL;
0170: }
0171: 
0172: 
0173: 
0174: 
0175: //-----------------------------------------------------------------------------
0176: // Name: InitDeviceObjects()
0177: // Desc: Initialize scene objects.
0178: //-----------------------------------------------------------------------------
0179: HRESULT CMyD3DApplication::InitDeviceObjects()
0180: {
0181:     // TODO: create device objects
0182: 
0183:     HRESULT hr;
0184: 
0185:     // Init the font
0186:     m_pFont->InitDeviceObjects( m_pd3dDevice );
0187: 
0188:     // Create a teapot mesh using D3DX
0189:     if( FAILED( hr = D3DXCreateTeapot( m_pd3dDevice, &m_pD3DXMesh, NULL ) ) )
0190:         return DXTRACE_ERR_NOMSGBOX( "D3DXCreateTeapot", hr );
0191: 
0192:     return S_OK;
0193: }
0194: 
0195: 
0196: 
0197: 
0198: //-----------------------------------------------------------------------------
0199: // Name: RestoreDeviceObjects()
0200: // Desc: Restores scene objects.
0201: //-----------------------------------------------------------------------------
0202: HRESULT CMyD3DApplication::RestoreDeviceObjects()
0203: {
0204:     // TODO: setup render states
0205: 
0206:     // Setup a material
0207:     D3DMATERIAL8 mtrl;
0208:     D3DUtil_InitMaterial( mtrl, 1.0f, 0.0f, 0.0f );
0209:     m_pd3dDevice->SetMaterial( &mtrl );
0210: 
0211:     // Set up the textures
0212:     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
0213:     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
0214:     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
0215:     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
0216:     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
0217: 
0218:     // Set miscellaneous render states
0219:     m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE,   FALSE );
0220:     m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE );
0221:     m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,        TRUE );
0222:     m_pd3dDevice->SetRenderState( D3DRS_AMBIENT,        0x000F0F0F );
0223: 
0224:     // Set the world matrix
0225:     D3DXMATRIX matIdentity;
0226:     D3DXMatrixIdentity( &matIdentity );
0227:     m_pd3dDevice->SetTransform( D3DTS_WORLD,  &matIdentity );
0228: 
0229:     // Set up our view matrix. A view matrix can be defined given an eye point,
0230:     // a point to lookat, and a direction for which way is up. Here, we set the
0231:     // eye five units back along the z-axis and up three units, look at the
0232:     // origin, and define "up" to be in the y-direction.
0233:     D3DXMATRIX matView;
0234:     D3DXVECTOR3 vFromPt   = D3DXVECTOR3( 0.0f, 0.0f, -5.0f );
0235:     D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
0236:     D3DXVECTOR3 vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
0237:     D3DXMatrixLookAtLH( &matView, &vFromPt, &vLookatPt, &vUpVec );
0238:     m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
0239: 
0240:     // Set the projection matrix
0241:     D3DXMATRIX matProj;
0242:     FLOAT fAspect = ((FLOAT)m_d3dsdBackBuffer.Width) / m_d3dsdBackBuffer.Height;
0243:     D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, 1.0f, 100.0f );
0244:     m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
0245: 
0246:     // Set up lighting states
0247:     D3DLIGHT8 light;
0248:     D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, -1.0f, -1.0f, 2.0f );
0249:     m_pd3dDevice->SetLight( 0, &light );
0250:     m_pd3dDevice->LightEnable( 0, TRUE );
0251:     m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
0252: 
0253:     // Restore the font
0254:     m_pFont->RestoreDeviceObjects();
0255: 
0256:     return S_OK;
0257: }
0258: 
0259: 
0260: 
0261: 
0262: //-----------------------------------------------------------------------------
0263: // Name: FrameMove()
0264: // Desc: Called once per frame, the call is the entry point for animating
0265: //       the scene.
0266: //-----------------------------------------------------------------------------
0267: HRESULT CMyD3DApplication::FrameMove()
0268: {
0269:     // TODO: update world
0270: 
0271:     // Update user input state
0272:     UpdateInput( &m_UserInput );
0273: 
0274:     // Update the world state according to user input
0275:     D3DXMATRIX matWorld;
0276:     D3DXMATRIX matRotY;
0277:     D3DXMATRIX matRotX;
0278: 
0279:     if( m_UserInput.bRotateLeft && !m_UserInput.bRotateRight )
0280:         m_fWorldRotY += m_fElapsedTime;
0281:     else if( m_UserInput.bRotateRight && !m_UserInput.bRotateLeft )
0282:         m_fWorldRotY -= m_fElapsedTime;
0283: 
0284:     if( m_UserInput.bRotateUp && !m_UserInput.bRotateDown )
0285:         m_fWorldRotX += m_fElapsedTime;
0286:     else if( m_UserInput.bRotateDown && !m_UserInput.bRotateUp )
0287:         m_fWorldRotX -= m_fElapsedTime;
0288: 
0289:     D3DXMatrixRotationX( &matRotX, m_fWorldRotX );
0290:     D3DXMatrixRotationY( &matRotY, m_fWorldRotY );
0291: 
0292:     D3DXMatrixMultiply( &matWorld, &matRotX, &matRotY );
0293:     m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
0294: 
0295:     return S_OK;
0296: }
0297: 
0298: 
0299: 
0300: 
0301: //-----------------------------------------------------------------------------
0302: // Name: UpdateInput()
0303: // Desc: Update the user input.  Called once per frame 
0304: //-----------------------------------------------------------------------------
0305: void CMyD3DApplication::UpdateInput( UserInput* pUserInput )
0306: {
0307:     pUserInput->bRotateUp    = ( m_bHasFocus && (GetAsyncKeyState( VK_UP )    & 0x8000) == 0x8000 );
0308:     pUserInput->bRotateDown  = ( m_bHasFocus && (GetAsyncKeyState( VK_DOWN )  & 0x8000) == 0x8000 );
0309:     pUserInput->bRotateLeft  = ( m_bHasFocus && (GetAsyncKeyState( VK_LEFT )  & 0x8000) == 0x8000 );
0310:     pUserInput->bRotateRight = ( m_bHasFocus && (GetAsyncKeyState( VK_RIGHT ) & 0x8000) == 0x8000 );
0311: }
0312: 
0313: 
0314: 
0315: 
0316: //-----------------------------------------------------------------------------
0317: // Name: Render()
0318: // Desc: Called once per frame, the call is the entry point for 3d
0319: //       rendering. This function sets up render states, clears the
0320: //       viewport, and renders the scene.
0321: //-----------------------------------------------------------------------------
0322: HRESULT CMyD3DApplication::Render()
0323: {
0324:     // Clear the viewport
0325:     m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
0326:                          0x000000ff, 1.0f, 0L );
0327: 
0328:     // Begin the scene
0329:     if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
0330:     {
0331:         // TODO: render world
0332:         
0333:         // Render the teapot mesh
0334:         m_pD3DXMesh->DrawSubset(0);
0335: 
0336:         // Render stats and help text  
0337:         RenderText();
0338: 
0339:         // End the scene.
0340:         m_pd3dDevice->EndScene();
0341:     }
0342: 
0343:     return S_OK;
0344: }
0345: 
0346: 
0347: 
0348: 
0349: //-----------------------------------------------------------------------------
0350: // Name: RenderText()
0351: // Desc: Renders stats and help text to the scene.
0352: //-----------------------------------------------------------------------------
0353: HRESULT CMyD3DApplication::RenderText()
0354: {
0355:     D3DCOLOR fontColor        = D3DCOLOR_ARGB(255,255,255,0);
0356:     D3DCOLOR fontWarningColor = D3DCOLOR_ARGB(255,0,255,255);
0357:     TCHAR szMsg[MAX_PATH] = TEXT("");
0358: 
0359:     // Output display stats
0360:     FLOAT fNextLine = 40.0f; 
0361: 
0362:     lstrcpy( szMsg, m_strDeviceStats );
0363:     fNextLine -= 20.0f;
0364:     m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
0365: 
0366:     lstrcpy( szMsg, m_strFrameStats );
0367:     fNextLine -= 20.0f;
0368:     m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
0369: 
0370:     // Output statistics & help
0371:     fNextLine = (FLOAT) m_d3dsdBackBuffer.Height; 
0372: 
0373:     wsprintf( szMsg, TEXT("Arrow keys: Up=%d Down=%d Left=%d Right=%d"), 
0374:               m_UserInput.bRotateUp, m_UserInput.bRotateDown, m_UserInput.bRotateLeft, m_UserInput.bRotateRight );
0375:     fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
0376: 
0377:     lstrcpy( szMsg, TEXT("Use arrow keys to rotate object") );
0378:     fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
0379: 
0380:     lstrcpy( szMsg, TEXT("Press 'F2' to configure display") );
0381:     fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
0382: 
0383:     return S_OK;
0384: }
0385: 
0386: 
0387: 
0388: 
0389: //-----------------------------------------------------------------------------
0390: // Name: MsgProc()
0391: // Desc: Overrrides the main WndProc, so the sample can do custom message
0392: //       handling (e.g. processing mouse, keyboard, or menu commands).
0393: //-----------------------------------------------------------------------------
0394: LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT msg, WPARAM wParam,
0395:                                     LPARAM lParam )
0396: {
0397:     switch( msg )
0398:     {
0399:         case WM_PAINT:
0400:         {
0401:             if( m_bLoadingApp )
0402:             {
0403:                 // Draw on the window tell the user that the app is loading
0404:                 // TODO: change as needed
0405:                 HDC hDC = GetDC( hWnd );
0406:                 TCHAR strMsg[MAX_PATH];
0407:                 wsprintf( strMsg, TEXT("Loading... Please wait") );
0408:                 RECT rct;
0409:                 GetClientRect( hWnd, &rct );
0410:                 DrawText( hDC, strMsg, -1, &rct, DT_CENTER|DT_VCENTER|DT_SINGLELINE );
0411:                 ReleaseDC( hWnd, hDC );
0412:             }
0413:             break;
0414:         }
0415: 
0416:     }
0417: 
0418:     return CD3DApplication::MsgProc( hWnd, msg, wParam, lParam );
0419: }
0420: 
0421: 
0422: 
0423: 
0424: //-----------------------------------------------------------------------------
0425: // Name: InvalidateDeviceObjects()
0426: // Desc: Invalidates device objects.  
0427: //-----------------------------------------------------------------------------
0428: HRESULT CMyD3DApplication::InvalidateDeviceObjects()
0429: {
0430:     // TODO: Cleanup any objects created in RestoreDeviceObjects()
0431:     m_pFont->InvalidateDeviceObjects();
0432: 
0433:     return S_OK;
0434: }
0435: 
0436: 
0437: 
0438: 
0439: //-----------------------------------------------------------------------------
0440: // Name: DeleteDeviceObjects()
0441: // Desc: Called when the app is exiting, or the device is being changed,
0442: //       this function deletes any device dependent objects.  
0443: //-----------------------------------------------------------------------------
0444: HRESULT CMyD3DApplication::DeleteDeviceObjects()
0445: {
0446:     // TODO: Cleanup any objects created in InitDeviceObjects()
0447:     m_pFont->DeleteDeviceObjects();
0448:     SAFE_RELEASE( m_pD3DXMesh );
0449: 
0450:     return S_OK;
0451: }
0452: 
0453: 
0454: 
0455: 
0456: //-----------------------------------------------------------------------------
0457: // Name: FinalCleanup()
0458: // Desc: Called before the app exits, this function gives the app the chance
0459: //       to cleanup after itself.
0460: //-----------------------------------------------------------------------------
0461: HRESULT CMyD3DApplication::FinalCleanup()
0462: {
0463:     // TODO: Perform any final cleanup needed
0464:     // Cleanup D3D font
0465:     SAFE_DELETE( m_pFont );
0466: 
0467:     // Write the settings to the registry
0468:     WriteSettings();
0469: 
0470:     return S_OK;
0471: }
0472: 
0473: 
0474: 
0475: 
0476: