⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winmain.cpp

📁 用DirectX制作高级动画-[Advanced.Animation.with.DirectX]
💻 CPP
字号:
#include <windows.h>

#include "d3d9.h"
#include "d3dx9.h"
#include "Direct3D.h"
#include "Particles.h"

// Direct3D objects
IDirect3D9       *g_pD3D       = NULL;
IDirect3DDevice9 *g_pD3DDevice = NULL;

// Helicopter smoke, tree, and people particle emitter objects
cParticleEmitter g_ChopperEmitter;
cParticleEmitter g_TreeEmitter;
cParticleEmitter g_PeopleEmitter;

// Helicopter, rotor, shadow, and backdrop mesh objects
D3DXMESHCONTAINER_EX *g_ChopperMesh  = NULL;
D3DXMESHCONTAINER_EX *g_RotorMesh    = NULL;
D3DXMESHCONTAINER_EX *g_ShadowMesh   = NULL;
D3DXMESHCONTAINER_EX *g_BackdropMesh = NULL;

// Helicopter's position and Y-axis rotation
D3DXVECTOR3 g_vecChopper = D3DXVECTOR3(0.0f, 50.0f, 0.0f);
float       g_rotChopper = 0.0f;

// Window class and caption text
char g_szClass[]   = "ParticlesClass";
char g_szCaption[] = "Particles Demo by Jim Adams";

// Function prototypes
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow);
long FAR PASCAL WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

BOOL DoInit(HWND hWnd);
void DoShutdown();
void DoFrame();

int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
{
  WNDCLASSEX wcex;
  MSG        Msg;
  HWND       hWnd;

  // Initialize the COM system
  CoInitialize(NULL);

  // Create the window class here and register it
  wcex.cbSize        = sizeof(wcex);
  wcex.style         = CS_CLASSDC;
  wcex.lpfnWndProc   = WindowProc;
  wcex.cbClsExtra    = 0;
  wcex.cbWndExtra    = 0;
  wcex.hInstance     = hInst;
  wcex.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
  wcex.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  wcex.lpszMenuName  = NULL;
  wcex.lpszClassName = g_szClass;
  wcex.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
  if(!RegisterClassEx(&wcex))
    return FALSE;

  // Create the main window
  hWnd = CreateWindow(g_szClass, g_szCaption,
              WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
              0, 0, 640, 480,
              NULL, NULL, hInst, NULL);
  if(!hWnd)
    return FALSE;
  ShowWindow(hWnd, SW_NORMAL);
  UpdateWindow(hWnd);

  // Call init function and enter message pump
  if(DoInit(hWnd) == TRUE) {

    // Start message pump, waiting for user to exit
    ZeroMemory(&Msg, sizeof(MSG));
    while(Msg.message != WM_QUIT) {
      if(PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
      }

      // Render a single frame
      DoFrame();
    }
  }

  // Call shutdown
  DoShutdown();
 
  // Unregister the window class
  UnregisterClass(g_szClass, hInst);

  // Shut down the COM system
  CoUninitialize();

  return 0;
}


long FAR PASCAL WindowProc(HWND hWnd, UINT uMsg,              \
                           WPARAM wParam, LPARAM lParam)
{
  // Only handle window destruction messages
  switch(uMsg) {
    case WM_DESTROY:
      PostQuitMessage(0);
      break;

    default:
      return DefWindowProc(hWnd, uMsg, wParam, lParam);
  }

  return 0;
}

BOOL DoInit(HWND hWnd)
{
  // Initialize Direct3D
  InitD3D(&g_pD3D, &g_pD3DDevice, hWnd);

  // Load the helicopter, rotor, and shadow meshes
  LoadMesh(&g_ChopperMesh, g_pD3DDevice, "..\\Data\\Chopper.x", "..\\Data\\");
  LoadMesh(&g_RotorMesh,   g_pD3DDevice, "..\\Data\\Rotor.x",   "..\\Data\\");
  LoadMesh(&g_ShadowMesh,  g_pD3DDevice, "..\\Data\\Shadow.x",  "..\\Data\\");

  // Load the backdrop mesh
  LoadMesh(&g_BackdropMesh, g_pD3DDevice, "..\\Data\\Backdrop.x", "..\\Data\\");

  // Create the particle emitters
  g_ChopperEmitter.Create(g_pD3DDevice, &D3DXVECTOR3(0.0f, 0.0f, 0.0f), EMITTER_CLOUD);
  g_TreeEmitter.Create(g_pD3DDevice,    &D3DXVECTOR3(0.0f, 0.0f, 0.0f), EMITTER_TREE);
  g_PeopleEmitter.Create(g_pD3DDevice,  &D3DXVECTOR3(0.0f, 0.0f, 0.0f), EMITTER_PEOPLE);

  // Populate the ground with trees and people
  DWORD Type = PARTICLE_TREE1;
  for(DWORD i=0;i<50;i++) {
    float rot  = (float)(rand() % 628) / 100.0f;
    float dist = (float)(rand() % 400);
    g_TreeEmitter.Add(Type++,
                      &D3DXVECTOR3((float)cos(rot)*dist,25.0f,(float)sin(rot)*dist),
                      50.0f, 0xFFFFFFFF, 0, &D3DXVECTOR3(0.0f, 0.0f, 0.0f));
    if(Type > PARTICLE_TREE3)
      Type = PARTICLE_TREE1;

    rot  = (float)(rand() % 628) / 100.0f;
    dist = (float)(rand() % 400);
    g_PeopleEmitter.Add(PARTICLE_PEOPLE1,
                      &D3DXVECTOR3((float)cos(rot)*dist,7.5f,(float)sin(rot)*dist),
                      15.0f, 0xFFFFFFFF, 0, &D3DXVECTOR3(0.0f, 0.0f, 0.0f));
  }

  // Setup a light
  D3DLIGHT9 Light;
  ZeroMemory(&Light, sizeof(D3DLIGHT9));
  Light.Type = D3DLIGHT_DIRECTIONAL;
  Light.Diffuse.r = Light.Diffuse.g = Light.Diffuse.b = Light.Diffuse.a = 1.0f;
  Light.Direction = D3DXVECTOR3(0.0f, -1.0f, 0.0f);
  g_pD3DDevice->SetLight(0, &Light);
  g_pD3DDevice->LightEnable(0, TRUE);

  // Play a chopper sound
  PlaySound("..\\Data\\Chopper.wav", NULL, SND_LOOP | SND_ASYNC);

  return TRUE;
}

void DoShutdown()
{
  // Stop the sound
  PlaySound(NULL, NULL, 0);

  // Release particle emitters
  g_ChopperEmitter.Free();
  g_TreeEmitter.Free();
  g_PeopleEmitter.Free();

  // Release meshes
  delete g_BackdropMesh; g_BackdropMesh = NULL;
  delete g_ShadowMesh;   g_ShadowMesh   = NULL;
  delete g_RotorMesh;    g_RotorMesh    = NULL;
  delete g_ChopperMesh;  g_ChopperMesh  = NULL;

  // Release D3D objects
  ReleaseCOM(g_pD3DDevice);
  ReleaseCOM(g_pD3D);
}

void DoFrame()
{
  static DWORD LastTime = timeGetTime();
  DWORD Time = timeGetTime();
  DWORD Elapsed;
  D3DXMATRIX matWorld;

  // Get elapsed time and update last frame's time
  Elapsed = Time - LastTime;
  LastTime = Time;

  // Rotate and move the helicopter
  g_rotChopper = (float)Time / 5000.0f;
  g_vecChopper.x += (float)cos(g_rotChopper) * ((float)Elapsed / 30.0f);
  g_vecChopper.z -= (float)sin(g_rotChopper) * ((float)Elapsed / 30.0f);

  // Call special function that creates smoke under helicopter
  g_ChopperEmitter.HandleSmoke(&g_vecChopper, Elapsed);

  // Call special function that makes people duck when chopper is too close
  g_PeopleEmitter.HandleDucking(&g_vecChopper);

  // Update the helicopter's particle emitter
  g_ChopperEmitter.Process(Elapsed);

  // Calculate a view transformation matrix
  D3DXMATRIX matView;
  D3DXMatrixLookAtLH(&matView,
                     &D3DXVECTOR3(g_vecChopper.x, 80.0f, g_vecChopper.z - 150.0f),
                     &D3DXVECTOR3(g_vecChopper.x, 0.0f, g_vecChopper.z),
                     &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
  g_pD3DDevice->SetTransform(D3DTS_VIEW, &matView);

  // Clear the device and start drawing the scene
  g_pD3DDevice->Clear(NULL, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0,0,64,255), 1.0f, 0);
  if(SUCCEEDED(g_pD3DDevice->BeginScene())) {

    // Turn on lighting
    g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);

    // Draw the backdrop mesh at origin
    D3DXMatrixIdentity(&matWorld);
    g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
    DrawMesh(g_BackdropMesh);

    // Draw the helicopter's shadow
    D3DXMatrixTranslation(&matWorld, g_vecChopper.x, 0.5f, g_vecChopper.z);
    g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
    DrawMesh(g_ShadowMesh);

    // Draw the helicopter
    D3DXMatrixRotationYawPitchRoll(&matWorld, g_rotChopper, 0.0f, -0.0872222f);
    matWorld._41 = g_vecChopper.x;  // Set position manually in matrix
    matWorld._42 = g_vecChopper.y;
    matWorld._43 = g_vecChopper.z;
    g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
    DrawMesh(g_ChopperMesh);

    // Draw the rotor (rotate and tilt it forward a bit and position above helicopter)
    D3DXMATRIX matRotY, matRotZ, matRotYY;
    D3DXMatrixRotationY(&matRotY, (float)Time / 10.0f);  // Turn rotor
    D3DXMatrixRotationZ(&matRotZ, -0.174444f);                    // Angle forward
    D3DXMatrixRotationY(&matRotYY, g_rotChopper);                 // Orient to chopper
    D3DXMatrixTranslation(&matWorld, g_vecChopper.x, g_vecChopper.y, g_vecChopper.z);
    g_pD3DDevice->SetTransform(D3DTS_WORLD, &(matRotY * matRotZ * matRotYY * matWorld));
    DrawMesh(g_RotorMesh);

    // Draw the particles (turn off lights and enable alpha testing)
    g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
    g_pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
    g_pD3DDevice->SetRenderState(D3DRS_ALPHAREF, 0x08);
    g_pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
    g_TreeEmitter.Render(&matView);
    g_PeopleEmitter.Render(&matView);

    // Enable alpha blending for the smoke particles
    g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
    g_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
    g_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
    g_ChopperEmitter.Render(&matView);
    g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);


    // End the scene
    g_pD3DDevice->EndScene();
  }

  // Present the scene to the user
  g_pD3DDevice->Present(NULL, NULL, NULL, NULL);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -