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

📄 winmain.cpp

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

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

// Vertex shader declaration and interfaces
D3DVERTEXELEMENT9 g_MorphBlendMeshDecl[] =
{
  // 1st stream is for base mesh
  { 0,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
  { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   0 },
  { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
  // 2nd stream is for mesh 1
  { 1,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 1 },
  { 1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   1 },
  { 1, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
  // 3rd stream is for mesh 2
  { 2,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 2 },
  { 2, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   2 },
  { 2, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2 },
  // 4th stream is for mesh 3
  { 3,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3 },
  { 3, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   3 },
  { 3, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3 },
  // 5th stream is for mesh 4
  { 4,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 4 },
  { 4, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   4 },
  { 4, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4 },
  D3DDECL_END()
};
IDirect3DVertexShader9      *g_VS   = NULL;
IDirect3DVertexDeclaration9 *g_Decl = NULL;

// Load mesh FVF
#define BLENDFVF (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)

// Base and target morphing mesh objects
D3DXMESHCONTAINER_EX *g_BaseMesh    = NULL;
D3DXMESHCONTAINER_EX *g_Mesh1       = NULL;
D3DXMESHCONTAINER_EX *g_Mesh2       = NULL;
D3DXMESHCONTAINER_EX *g_Mesh3       = NULL;
D3DXMESHCONTAINER_EX *g_Mesh4       = NULL;

// Flags to toggle blending
BOOL g_BlendMesh1 = TRUE;
BOOL g_BlendMesh2 = TRUE;
BOOL g_BlendMesh3 = TRUE;
BOOL g_BlendMesh4 = TRUE;

// Guide texture and sprite interface
IDirect3DTexture9 *g_GuideTexture = NULL;
ID3DXSprite       *g_Guide        = NULL;

// Window class and caption text
char g_szClass[]   = "BlendedVSMorphClass";
char g_szCaption[] = "Blended Vertex Shader Morphing 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();

void DrawBlendedMesh(D3DXMESHCONTAINER_EX *BaseMesh,
                     D3DXMESHCONTAINER_EX *Mesh1, float Blend1,
                     D3DXMESHCONTAINER_EX *Mesh2, float Blend2,
                     D3DXMESHCONTAINER_EX *Mesh3, float Blend3,
                     D3DXMESHCONTAINER_EX *Mesh4, float Blend4);

///////////////////////////////////////////////////////////
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 = NULL;
  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)
{
  switch(uMsg) {
    case WM_KEYUP:
      switch(wParam) {
        case '1':
          g_BlendMesh1 = (g_BlendMesh1==TRUE)?FALSE:TRUE;
          break;

        case '2':
          g_BlendMesh2 = (g_BlendMesh2==TRUE)?FALSE:TRUE;
          break;

        case '3':
          g_BlendMesh3 = (g_BlendMesh3==TRUE)?FALSE:TRUE;
          break;

        case '4':
          g_BlendMesh4 = (g_BlendMesh4==TRUE)?FALSE:TRUE;
          break;

        case ' ':
          g_BlendMesh1 = g_BlendMesh2 = g_BlendMesh3 = g_BlendMesh4 = TRUE;
          break;
      }
      break;

    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 base and target meshes using the blended morphing FVF
  LoadMesh(&g_BaseMesh, g_pD3DDevice, "..\\Data\\Base.x",  "..\\Data\\", BLENDFVF);
  LoadMesh(&g_Mesh1,    g_pD3DDevice, "..\\Data\\Mesh1.x", "..\\Data\\", BLENDFVF);
  LoadMesh(&g_Mesh2,    g_pD3DDevice, "..\\Data\\Mesh2.x", "..\\Data\\", BLENDFVF);
  LoadMesh(&g_Mesh3,    g_pD3DDevice, "..\\Data\\Mesh3.x", "..\\Data\\", BLENDFVF);
  LoadMesh(&g_Mesh4,    g_pD3DDevice, "..\\Data\\Mesh4.x", "..\\Data\\", BLENDFVF);

   // Load the vertex shader
  LoadVertexShader(&g_VS, g_pD3DDevice, "MorphBlend.vsh", g_MorphBlendMeshDecl, &g_Decl);

 // Load the guide texture and create the sprite interface
  D3DXCreateTextureFromFileEx(g_pD3DDevice, "..\\Data\\Guide.bmp", 
                              D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0,
                              D3DFMT_A1R5G5B5, D3DPOOL_DEFAULT, D3DX_DEFAULT, 
                              D3DX_DEFAULT, 0xFF000000,
                              NULL, NULL, &g_GuideTexture);
  D3DXCreateSprite(g_pD3DDevice, &g_Guide);

  return TRUE;
}

void DoShutdown()
{
  // Free all meshes
  delete g_BaseMesh;
  delete g_Mesh1;
  delete g_Mesh2;
  delete g_Mesh3;
  delete g_Mesh4;

  // Free guide texture and sprite interface
  ReleaseCOM(g_GuideTexture);
  ReleaseCOM(g_Guide);

  // Free shader interfaces
  ReleaseCOM(g_VS);
  ReleaseCOM(g_Decl);

  // Shutdown Direct3D
  ReleaseCOM(g_pD3DDevice);
  ReleaseCOM(g_pD3D);
}

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

    // Set a view transformation
    D3DXMATRIX matView;
    D3DXMatrixLookAtLH(&matView,
                       &D3DXVECTOR3(-5.0f, 4.0f, -12.0f),
                       &D3DXVECTOR3(0.0f, 0.0f, 0.0f),
                       &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
    g_pD3DDevice->SetTransform(D3DTS_VIEW, &matView);

    // Set a world transformation
    D3DXMATRIX matWorld;
    D3DXMatrixIdentity(&matWorld);
    g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);

    // Calculate the blending scalar values based on time
    DWORD Time = timeGetTime();
    float Mesh1Blend = (float)(Time %  501) /  250.0f;
    float Mesh2Blend = (float)(Time % 1001) /  500.0f;
    float Mesh3Blend = (float)(Time % 2001) / 1000.0f;
    float Mesh4Blend = (float)(Time % 3001) / 1500.0f;

    // Apply toggles to meshes
    if(g_BlendMesh1 == FALSE)
      Mesh1Blend = 0.0f;
    if(g_BlendMesh2 == FALSE)
      Mesh2Blend = 0.0f;
    if(g_BlendMesh3 == FALSE)
      Mesh3Blend = 0.0f;
    if(g_BlendMesh4 == FALSE)
      Mesh4Blend = 0.0f;

    // Draw the blended mesh
    DrawBlendedMesh(g_BaseMesh,
                    g_Mesh1, ((Mesh1Blend<=1.0f)?Mesh1Blend:(2.0f-Mesh1Blend)),
                    g_Mesh2, ((Mesh2Blend<=1.0f)?Mesh2Blend:(2.0f-Mesh2Blend)),
                    g_Mesh3, ((Mesh3Blend<=1.0f)?Mesh3Blend:(2.0f-Mesh3Blend)),
                    g_Mesh4, ((Mesh4Blend<=1.0f)?Mesh4Blend:(2.0f-Mesh4Blend)));

    // Draw the guide
    g_Guide->Draw(g_GuideTexture, NULL, NULL, NULL, 0.0f, &D3DXVECTOR2(0.0f, 0.0f), 0xFFFFFFFF);

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

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

void DrawBlendedMesh(D3DXMESHCONTAINER_EX *BaseMesh,
                     D3DXMESHCONTAINER_EX *Mesh1, float Blend1,
                     D3DXMESHCONTAINER_EX *Mesh2, float Blend2,
                     D3DXMESHCONTAINER_EX *Mesh3, float Blend3,
                     D3DXMESHCONTAINER_EX *Mesh4, float Blend4)
{
  // Enable zbuffering
  g_pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);

  // Get the world, view, and projection matrices
  D3DXMATRIX matWorld, matView, matProj;
  g_pD3DDevice->GetTransform(D3DTS_WORLD, &matWorld);
  g_pD3DDevice->GetTransform(D3DTS_VIEW, &matView);
  g_pD3DDevice->GetTransform(D3DTS_PROJECTION, &matProj);

  // Get the world*view*proj matrix and set it
  D3DXMATRIX matWVP;
  matWVP = matWorld * matView * matProj;
  D3DXMatrixTranspose(&matWVP, &matWVP);
  g_pD3DDevice->SetVertexShaderConstantF(0, (float*)&matWVP, 4);

  // Set the scalar blending values to use
  g_pD3DDevice->SetVertexShaderConstantF(4, (float*)&D3DXVECTOR4(Blend1, Blend2, Blend3, Blend4), 1);

  // Set the light direction
  g_pD3DDevice->SetVertexShaderConstantF(5, (float*)&D3DXVECTOR4(0.5f, -0.5f, 1.0f, 0.0f), 1);

  // Get the meshes' vertex buffers
  IDirect3DVertexBuffer9 *pVB1 = NULL;
  IDirect3DVertexBuffer9 *pVB2 = NULL;
  IDirect3DVertexBuffer9 *pVB3 = NULL;
  IDirect3DVertexBuffer9 *pVB4 = NULL;
  g_Mesh1->MeshData.pMesh->GetVertexBuffer(&pVB1);
  g_Mesh2->MeshData.pMesh->GetVertexBuffer(&pVB2);
  g_Mesh3->MeshData.pMesh->GetVertexBuffer(&pVB3);
  g_Mesh4->MeshData.pMesh->GetVertexBuffer(&pVB4);

  // Set the stream sources
  g_pD3DDevice->SetStreamSource(1, pVB1, 0, D3DXGetFVFVertexSize(g_Mesh1->MeshData.pMesh->GetFVF()));
  g_pD3DDevice->SetStreamSource(2, pVB2, 0, D3DXGetFVFVertexSize(g_Mesh2->MeshData.pMesh->GetFVF()));
  g_pD3DDevice->SetStreamSource(3, pVB3, 0, D3DXGetFVFVertexSize(g_Mesh3->MeshData.pMesh->GetFVF()));
  g_pD3DDevice->SetStreamSource(4, pVB4, 0, D3DXGetFVFVertexSize(g_Mesh4->MeshData.pMesh->GetFVF()));

  // Draw the mesh in the vertex shader
  DrawMesh(g_BaseMesh, g_VS, g_Decl);

  // Clear the stream sources
  g_pD3DDevice->SetStreamSource(1, NULL, 0, 0);
  g_pD3DDevice->SetStreamSource(2, NULL, 0, 0);
  g_pD3DDevice->SetStreamSource(3, NULL, 0, 0);
  g_pD3DDevice->SetStreamSource(4, NULL, 0, 0);
  
  // Free the vertex buffer interface
  ReleaseCOM(pVB1);
  ReleaseCOM(pVB2);
  ReleaseCOM(pVB3);
  ReleaseCOM(pVB4);
}

⌨️ 快捷键说明

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