CG - N3 - 2014 2S

#include <Windows.h>
    #include <d3d9.h>
    #include <d3dx9.h>
    #include <math.h>
    #include <"strsafe.h">
    #include <string>
    #include <iostream>

    #pragma comment (lib, "d3d9.lib")
    #pragma comment (lib, "d3dx9.lib")


    #define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_NORMAL) 
    #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)

    using namespace std;

    CONST UINT SCREEN_WIDTH (1024);
    CONST UINT SCREEN_HEIGHT (768);
    CONST FLOAT ASPECT_RATIO ((FLOAT)SCREEN_WIDTH/(FLOAT)SCREEN_HEIGHT);

    LPD3DXMESH Alavanca;      
    DWORD numMateriaisAlavanca;
    D3DMATERIAL9* materialAlavanca;   
    LPDIRECT3DTEXTURE9* texturaAlavanca; 

    LPD3DXMESH Roda;      
    DWORD numMateriaisRoda;
    D3DMATERIAL9* materialRoda;   
    LPDIRECT3DTEXTURE9* texturaRoda; 

    std::wstring caminhoApp;

    int appRodando = 1;

     struct OURCUSTOMVERTEX 
     {
         float x,y,z;
         D3DVECTOR NORMAL;
     };
     
     LRESULT CALLBACK TratamentoEventos(HWND han_Wind,UINT uint_Message,WPARAM parameter1,LPARAM parameter2)
     {
         switch(uint_Message)
         {
             case WM_KEYDOWN:
             {
                 //bazinga
                 break;
             }
             break;
         }
     
         return DefWindowProc(han_Wind,uint_Message,parameter1,parameter2);
     }
     
     HWND NewWindow(LPCTSTR str_Title,int int_XPos, int int_YPos, int int_Width, int int_Height)
     {
         WNDCLASSEX estruturaJanela;
     
         estruturaJanela.cbSize = sizeof(WNDCLASSEX);
         estruturaJanela.style = CS_HREDRAW | CS_VREDRAW;
         estruturaJanela.lpfnWndProc = TratamentoEventos;
         estruturaJanela.cbClsExtra = 0;
         estruturaJanela.cbWndExtra = 0;
         estruturaJanela.hInstance = GetModuleHandle(NULL);
         estruturaJanela.hIcon = NULL;
         estruturaJanela.hCursor = NULL;
         estruturaJanela.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
         estruturaJanela.lpszMenuName = NULL;
         estruturaJanela.lpszClassName = L"WindowClassName";
         estruturaJanela.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
     
         RegisterClassEx(&estruturaJanela);
     
         return CreateWindowEx(WS_EX_CONTROLPARENT, L"WindowClassName", str_Title, WS_OVERLAPPED | WS_POPUP, 0, 0, int_Width, int_Height, NULL, NULL, GetModuleHandle(NULL), NULL);
     }

    void CriaLuz(LPDIRECT3DDEVICE9 placaVideo)
    {
        D3DLIGHT9 light;
        D3DMATERIAL9 material;

        ZeroMemory(&light, sizeof(light));
        light.Type = D3DLIGHT_DIRECTIONAL;    
        light.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
        light.Position = D3DXVECTOR3(0.0f, 1.0f, 100.0f);
        light.Direction = D3DXVECTOR3(0.0f, 0.0f, -1.0f);
        light.Range = 40.0f;    
        light.Phi = D3DXToRadian(50.0f);    
        light.Theta = D3DXToRadian(40.0f);    
        light.Falloff = 1.0f;    

        placaVideo->SetLight(0, &light);
        placaVideo->LightEnable(0, TRUE);

        ZeroMemory(&material, sizeof(D3DMATERIAL9));
        material.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
        material.Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);

        placaVideo->SetMaterial(&material); 
    }
     
     LPDIRECT3DDEVICE9 InicializaPlacaVideo(HWND han_WindowToBindTo)
     {

         LPDIRECT3D9 directX;
         LPDIRECT3DDEVICE9 placaVideo;
     
         directX = Direct3DCreate9(D3D_SDK_VERSION);
         if (directX == NULL)
         {
             MessageBox(han_WindowToBindTo,L"DirectX Runtime library not installed!",L"InicializaPlacaVideo()",MB_OK);
         }
     
         D3DPRESENT_PARAMETERS parametrosApresentacao;
         ZeroMemory( metrosApresentacao, sizeof(parametrosApresentacao) );
         parametrosApresentacao.Windowed = FALSE;
         parametrosApresentacao.BackBufferWidth = 1024;
         parametrosApresentacao.BackBufferHeight = 768;
         parametrosApresentacao.SwapEffect = D3DSWAPEFFECT_DISCARD;
         parametrosApresentacao.BackBufferFormat = D3DFMT_A8R8G8B8;
         parametrosApresentacao.BackBufferWidth = SCREEN_WIDTH;
         parametrosApresentacao.BackBufferHeight = SCREEN_HEIGHT;

         parametrosApresentacao.EnableAutoDepthStencil = TRUE;   
         parametrosApresentacao.AutoDepthStencilFormat = D3DFMT_D16; 
     
          if (FAILED(directX->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, han_WindowToBindTo, D3DCREATE_HARDWARE_VERTEXPROCESSING, metrosApresentacao, &placaVideo)))
          {
                 if (FAILED(directX->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, han_WindowToBindTo, D3DCREATE_SOFTWARE_VERTEXPROCESSING, metrosApresentacao, &placaVideo)))
                 {
                     MessageBox(han_WindowToBindTo,L"Failed to create even the reference device!",L"InicializaPlacaVideo()",MB_OK);
                 }
          }

          //Alavanca
          LPD3DXBUFFER bufferMaterialAlavanca; 
          std::wstring arquivo = L"alavanca.X";
          std::wstring caminhoModelo;
          caminhoModelo = caminhoApp.c_str();
          caminhoModelo.append(arquivo);

          D3DXLoadMeshFromX(caminhoModelo.c_str(),    
                      D3DXMESH_SYSTEMMEM,    
                      placaVideo,    
                      NULL,    
                      &bufferMaterialAlavanca,    
                      NULL,    
                      &numMateriaisAlavanca,    
                      &Alavanca);
        
        D3DXMATERIAL* tempMaterials = (D3DXMATERIAL*)bufferMaterialAlavanca->GetBufferPointer();

        materialAlavanca = new D3DMATERIAL9[numMateriaisAlavanca];
        texturaAlavanca = new LPDIRECT3DTEXTURE9[numMateriaisAlavanca]; //2-) Iniciamos o array

        for(DWORD i = 0; i < numMateriaisAlavanca; i++)    
        {
            materialAlavanca[i] = tempMaterials[i].MatD3D;    
            materialAlavanca[i].Ambient = materialAlavanca[i].Diffuse;    

            //3-) Carregamos o materialAlavanca
            try
            {
                if(FAILED(D3DXCreateTextureFromFileA(
                                                placaVideo,
                                                tempMaterials[i].pTextureFilename,
                                                &texturaAlavanca[i])))
                {
                    texturaAlavanca[i] = NULL;
                }
            }
            catch(exception)
            {
                texturaAlavanca[i] = NULL;
            }
        }


        //Roda
          LPD3DXBUFFER bufferMaterialRoda; 
          arquivo = L"Roda.X";
          caminhoModelo = caminhoApp.c_str();
          caminhoModelo.append(arquivo);

          D3DXLoadMeshFromX(caminhoModelo.c_str(),    
                      D3DXMESH_SYSTEMMEM,    
                      placaVideo,    
                      NULL,    
                      &bufferMaterialRoda,    
                      NULL,    
                      &numMateriaisRoda,    
                      &Roda);
        
        tempMaterials = (D3DXMATERIAL*)bufferMaterialRoda->GetBufferPointer();

        materialRoda = new D3DMATERIAL9[numMateriaisRoda];
        texturaRoda = new LPDIRECT3DTEXTURE9[numMateriaisRoda]; //2-) Iniciamos o array

        for(DWORD i = 0; i < numMateriaisRoda; i++)    
        {
            materialRoda[i] = tempMaterials[i].MatD3D;    
            materialRoda[i].Ambient = materialRoda[i].Diffuse;    

            //3-) Carregamos o materialRoda
            try
            {
                if(FAILED(D3DXCreateTextureFromFileA(
                                                placaVideo,
                                                tempMaterials[i].pTextureFilename,
                                                &texturaRoda[i])))
                {
                    texturaRoda[i] = NULL;
                }
            }
            catch(exception)
            {
                texturaRoda[i] = NULL;
            }
        }



          placaVideo->SetRenderState(D3DRS_LIGHTING, TRUE); 
          placaVideo->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(88, 55, 37));    
          placaVideo->SetRenderState(D3DRS_ZENABLE, TRUE);    
          placaVideo->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 

          //6-) Filtro de Textura
            placaVideo->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 8);
            placaVideo->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
            placaVideo->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
            placaVideo->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

          CriaLuz(placaVideo);
     
         return placaVideo;
     }

     void desenhaAlavanca(LPDIRECT3DDEVICE9 placaVideo)
     {
        for(DWORD i = 0; i < numMateriaisAlavanca; i++)    // Desenha a Alavanca
        {
            placaVideo->SetMaterial(&materialAlavanca[i]); 

            Alavanca->DrawSubset(i); 
            if(texturaAlavanca[i] != NULL)    
            {
                placaVideo->SetTexture(0, texturaAlavanca[i]);   
            }
        }
     }

      void desenhaRoda(LPDIRECT3DDEVICE9 placaVideo)
     {
        for(DWORD i = 0; i < numMateriaisRoda; i++)    // Desenha a Roda
        {
            placaVideo->SetMaterial(&materialRoda[i]); 

            Roda->DrawSubset(i); 
            if(texturaRoda[i] != NULL)    
            {
                placaVideo->SetTexture(0, texturaRoda[i]);   
            }
        }
     }

    int angulo;
    bool lado;
     void DesenhaCena(LPDIRECT3DDEVICE9 placaVideo)
     {

         if(KEY_DOWN(VK_ESCAPE)){
             appRodando = 0;
         }

         if(KEY_DOWN(VK_LEFT)){
             lado = true;
         }

         if(KEY_DOWN(VK_RIGHT)){
             lado = false;
         }

         placaVideo->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); 
         placaVideo->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
         placaVideo->BeginScene();
     
         placaVideo->SetFVF(CUSTOMFVF);

         D3DXMATRIX matView;
         D3DXMatrixLookAtLH(
             &matView,
             &D3DXVECTOR3(0.0f, 0.0f, 300.0f), 
             &D3DXVECTOR3(0.0f,0.0f, 0.0f),
             &D3DXVECTOR3(0.0f, 1.0f, 0.0f));

         placaVideo->SetTransform(D3DTS_VIEW, &matView);

         D3DXMATRIX matProjection;

         D3DXMatrixPerspectiveFovLH(
             &matProjection,
             D3DXToRadian(45),
             ASPECT_RATIO,
             1.0f,
             1000.0f);
         placaVideo->SetTransform(D3DTS_PROJECTION, &matProjection);

         if(lado){
            angulo--;
         } else {
            angulo++;
         }

         D3DXMATRIX matrizWorldAlavanca;
         D3DXMatrixRotationX(&matrizWorldAlavanca, D3DXToRadian(90));
         D3DXMATRIX matAlav;
         D3DXMatrixTranslation (&matAlav, 5, 160.0f, -450.0f);
         D3DXMATRIX matGiraAlav;
         D3DXMatrixRotationZ(&matGiraAlav, D3DXToRadian(angulo));
         D3DXMATRIX matLOL; //matriz da risada
         D3DXMatrixRotationY(&matLOL, D3DXToRadian(10));
         matGiraAlav = matLOL*matGiraAlav;
         placaVideo->SetTransform(D3DTS_WORLD, &(matrizWorldAlavanca * matAlav * matGiraAlav));
         desenhaAlavanca(placaVideo);

         D3DXMATRIX matrizWorldRoda;
         D3DXMatrixRotationX(&matrizWorldRoda, D3DXToRadian(90));
         D3DXMATRIX matPosRoda;
         D3DXMatrixTranslation (&matPosRoda, 0, 0, -500.0f);
         D3DXMATRIX matGiraRoda;
         D3DXMatrixRotationZ (&matGiraRoda, D3DXToRadian(angulo));

         placaVideo->SetTransform(D3DTS_WORLD, &(matrizWorldRoda*matPosRoda*matGiraRoda));
         desenhaRoda(placaVideo);



         placaVideo->EndScene();
         placaVideo->Present(NULL, NULL, NULL, NULL);
     }

     int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPreviousInstance,LPSTR lpcmdline,int nCmdShow)
     {
         MSG msg_Message;
     
         HWND han_Window                   = NewWindow(L"DIRECTX", 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
         LPDIRECT3DDEVICE9 placaVideo      = InicializaPlacaVideo(han_Window);
     
         while(appRodando)
         {
             if(PeekMessage(&msg_Message,han_Window,0,0,PM_REMOVE))
             {
                 DispatchMessage(&msg_Message);
             }
             DesenhaCena(placaVideo);
         }
     
         Alavanca->Release();
         Roda->Release();
         placaVideo->Release();
         DestroyWindow(han_Window);
     
         return 0;
     }