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

📄 winmain.cpp

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

// Ragdoll animation object
cRagdoll g_Ragdoll;

// Collision object collection 
cCollision g_Collision;

// Structure to contain sphere collision object data
typedef struct {
  D3DXVECTOR3 vecSphere;
  float       Scale;
} sCollisionSphere;
sCollisionSphere *g_SphereObjects = NULL;

typedef struct {
  D3DXVECTOR3 vecPos;
  DWORD Color;
  float       u, v;
} sVertex;
#define FVF (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)

// Floor's vertex buffer and texture
IDirect3DVertexBuffer9 *g_FloorVB = NULL;
IDirect3DTexture9      *g_FloorTexture = NULL;

// Mesh collection and frame hierarchy
D3DXMESHCONTAINER_EX *g_Mesh  = NULL;
D3DXFRAME_EX         *g_Frame = NULL;

// A ball mesh used to draw sphere collision objects
D3DXMESHCONTAINER_EX *g_Sphere = NULL;

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

// Window class and caption text
char g_szClass[]   = "RagdollClass";
char g_szCaption[] = "Ragdoll Animation 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 a skeletal mesh
  LoadMesh(&g_Mesh, &g_Frame, g_pD3DDevice, "..\\Data\\ragdoll.x", "..\\Data\\");

  // Create the ragdoll object to work with
  D3DXMATRIX matPosition;
  D3DXMatrixTranslation(&matPosition, 0.0f, 20.0f, 0.0f);
  g_Ragdoll.Create(g_Frame, g_Mesh, &matPosition);

  // Add the floor's plane
  g_Collision.AddPlane(&D3DXPLANE(0.0f, 1.0f, 0.0f, 0.0f));

  // Create the floor object
  g_pD3DDevice->CreateVertexBuffer(sizeof(sVertex)*4, D3DUSAGE_WRITEONLY, FVF, D3DPOOL_DEFAULT, &g_FloorVB, NULL);
  sVertex *VBPtr;
  g_FloorVB->Lock(0, 0, (void**)&VBPtr, 0);
  VBPtr[0].vecPos = D3DXVECTOR3(-2000.0f, 0.0f,  2000.0f);
  VBPtr[0].u = 0.0f; VBPtr[0].v = 0.0f; VBPtr[0].Color = 0xFFFFFFFF;
  VBPtr[1].vecPos = D3DXVECTOR3( 2000.0f, 0.0f,  2000.0f);
  VBPtr[1].u = 4.0f; VBPtr[1].v = 0.0f; VBPtr[1].Color = 0xFFFFFFFF;
  VBPtr[2].vecPos = D3DXVECTOR3(-2000.0f, 0.0f, -2000.0f);
  VBPtr[2].u = 0.0f; VBPtr[2].v = 4.0f; VBPtr[2].Color = 0xFFFFFFFF;
  VBPtr[3].vecPos = D3DXVECTOR3( 2000.0f, 0.0f, -2000.0f);
  VBPtr[3].u = 4.0f; VBPtr[3].v = 4.0f; VBPtr[3].Color = 0xFFFFFFFF;
  g_FloorVB->Unlock();

  // Load the floor texture
  D3DXCreateTextureFromFile(g_pD3DDevice, "..\\Data\\Floor.bmp", &g_FloorTexture);

  // Load the sphere mesh
  LoadMesh(&g_Sphere, g_pD3DDevice, "..\\Data\\Sphere.x", "..\\Data\\");

  // Create some sphere collision objects
  srand(timeGetTime());
  g_SphereObjects = new sCollisionSphere[15];
  for(DWORD i=0;i<15;i++) {
    g_SphereObjects[i].vecSphere = D3DXVECTOR3((float)(rand()%20)-10.0f,
                                               (float)(rand()%20),
                                               (float)(rand()%20)-10.0f);
    g_SphereObjects[i].Scale = (float)(rand() % 5) + 1.0f;

    g_Collision.AddSphere(&g_SphereObjects[i].vecSphere, g_SphereObjects[i].Scale);
  }

  return TRUE;
}

void DoShutdown()
{
  // Free sphere
  delete g_Sphere; g_Sphere = NULL;

  // Free floor and texture
  ReleaseCOM(g_FloorTexture);
  ReleaseCOM(g_FloorVB);

  // Free the ragdoll and collision data
  g_Ragdoll.Free();
  g_Collision.Free();

  // Free mesh and frame data
  delete g_Mesh;  g_Mesh  = NULL;
  delete g_Frame; g_Frame = NULL;

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

void DoFrame()
{
  static DWORD LastTime = timeGetTime() - 1;
  DWORD ThisTime = timeGetTime();

  // Calculate the elapsed time
  DWORD Elapsed = ThisTime - LastTime;
  LastTime = ThisTime;

  // Resolve the motion for this time-period
  g_Ragdoll.Resolve((float)Elapsed / 1000.0f,
                    -0.5f, -0.4f,
                    &D3DXVECTOR3(0.0f, -9.8f, 0.0f), 
                    &g_Collision);

  // Rebuild the ragdoll's frame hierarchy
  g_Ragdoll.RebuildHierarchy();

  // Build the skinned mesh
  UpdateMesh(g_Mesh);

  // Calculate a view transformation matrix
  D3DXVECTOR3 vecPos = g_Ragdoll.GetBone(0)->m_State.m_vecPosition;
  D3DXMATRIX matView;
  D3DXMatrixLookAtLH(&matView, 
                     &D3DXVECTOR3(vecPos.x, vecPos.y+10.0f, vecPos.z-20.0f),
                     &vecPos,
                     &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);

  // 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())) {

    // Render the floor
    g_pD3DDevice->SetTexture(0, g_FloorTexture);
    g_pD3DDevice->SetStreamSource(0, g_FloorVB, 0, sizeof(sVertex));
    g_pD3DDevice->SetFVF(FVF);
    g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

    // Render the spheres
    for(DWORD i=0;i<15;i++) {
      D3DXMatrixScaling(&matWorld, g_SphereObjects[i].Scale,
                                   g_SphereObjects[i].Scale,
                                   g_SphereObjects[i].Scale);
      matWorld._41 = g_SphereObjects[i].vecSphere.x;
      matWorld._42 = g_SphereObjects[i].vecSphere.y;
      matWorld._43 = g_SphereObjects[i].vecSphere.z;
      g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
      DrawMesh(g_Sphere);
    }

    D3DXMatrixIdentity(&matWorld);
    g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);

    // Render skinned mesh
    DrawMesh(g_Mesh);

    // 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 + -