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

📄 direct3d.cpp

📁 用DirectX制作高级动画-[Advanced.Animation.with.DirectX]
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include "Direct3D.h"

///////////////////////////////////////////////////////////
//
// Initialize Direct3D function
//
///////////////////////////////////////////////////////////
HRESULT InitD3D(IDirect3D9 **ppD3D, 
                IDirect3DDevice9 **ppD3DDevice,
                HWND hWnd, 
                BOOL ForceWindowed,
                BOOL MultiThreaded)
{
  IDirect3D9       *pD3D       = NULL;
  IDirect3DDevice9 *pD3DDevice = NULL;
  HRESULT           hr;

  // Error checking
  if(!ppD3D || !ppD3DDevice || !hWnd)
    return E_FAIL;

  // Initialize Direct3D
  if((pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
    return E_FAIL;
  *ppD3D = pD3D;

  // Ask if user wants to run windowed or fullscreen
  // or force windowed if flagged to do such
  int Mode;
  if(ForceWindowed == TRUE)
    Mode = IDNO;
  else
    Mode = MessageBox(hWnd, "Use fullscreen mode? (640x480x16)", "Initialize D3D", MB_YESNO | MB_ICONQUESTION);

  // Set the video (depending on windowed mode or fullscreen)
  D3DPRESENT_PARAMETERS d3dpp;
  ZeroMemory(&d3dpp, sizeof(d3dpp));

  // Setup video settings based on choice of fullscreen or not
  if(Mode == IDYES) {

    //////////////////////////////////////////////////////////
    // Setup fullscreen format (set to your own if you prefer)
    //////////////////////////////////////////////////////////
    DWORD     Width  = 640;
    DWORD     Height = 480;
    D3DFORMAT Format = D3DFMT_R5G6B5;

    // Set the presentation parameters (use fullscreen)
    d3dpp.BackBufferWidth  = Width;
    d3dpp.BackBufferHeight = Height;
    d3dpp.BackBufferFormat = Format;
    d3dpp.SwapEffect       = D3DSWAPEFFECT_FLIP;
    d3dpp.Windowed         = FALSE;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
    d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_DEFAULT;
  } else {

    //////////////////////////////////////////////////////////
    // Setup windowed format (set to your own dimensions below)
    //////////////////////////////////////////////////////////

    // Get the client and window dimensions
    RECT ClientRect, WndRect;
    GetClientRect(hWnd, &ClientRect);
    GetWindowRect(hWnd, &WndRect);

    // Set the width and height (set your dimensions here)
    DWORD DesiredWidth  = 640;
    DWORD DesiredHeight = 480;
    DWORD Width  = (WndRect.right - WndRect.left) + (DesiredWidth  - ClientRect.right);
    DWORD Height = (WndRect.bottom - WndRect.top) + (DesiredHeight - ClientRect.bottom);

    // Set the window's dimensions
    MoveWindow(hWnd, WndRect.left, WndRect.top, Width, Height, TRUE);

    // Get the desktop format
    D3DDISPLAYMODE d3ddm;
    pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);

    // Set the presentation parameters (use windowed)
    d3dpp.BackBufferWidth  = DesiredWidth;
    d3dpp.BackBufferHeight = DesiredHeight;
    d3dpp.BackBufferFormat = d3ddm.Format;
    d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
    d3dpp.Windowed         = TRUE;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
    d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_DEFAULT;
  }

  // Create the 3-D device
  DWORD Flags= D3DCREATE_MIXED_VERTEXPROCESSING;
//  DWORD Flags= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  if(MultiThreaded == TRUE)
    Flags |= D3DCREATE_MULTITHREADED;
  if(FAILED(hr = pD3D->CreateDevice(
                       D3DADAPTER_DEFAULT, 
                       D3DDEVTYPE_HAL, hWnd, Flags, 
                       &d3dpp, &pD3DDevice)))
      return hr;

  // Store the 3-D device object pointer
  *ppD3DDevice = pD3DDevice;

  // Set the perspective projection
  float Aspect = (float)d3dpp.BackBufferWidth / (float)d3dpp.BackBufferHeight;
  D3DXMATRIX matProjection;
  D3DXMatrixPerspectiveFovLH(&matProjection, D3DX_PI/4.0f, Aspect, 1.0f, 10000.0f);
  pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProjection);

  // Set the default render states
  pD3DDevice->SetRenderState(D3DRS_LIGHTING,         FALSE);
  pD3DDevice->SetRenderState(D3DRS_ZENABLE,          D3DZB_TRUE);
  pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE,  FALSE);

  // Set the default texture stage states
  pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_MODULATE);

  // Set the default texture filters
  pD3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  pD3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

  return S_OK;
}


///////////////////////////////////////////////////////////
//
// Load a vertex shader function
//
///////////////////////////////////////////////////////////
HRESULT LoadVertexShader(IDirect3DVertexShader9 **ppShader, 
                         IDirect3DDevice9 *pDevice,
                         char *Filename,
                         D3DVERTEXELEMENT9 *pElements,
                         IDirect3DVertexDeclaration9 **ppDecl)
{
  HRESULT hr;

  // Error checking
  if(!ppShader || !pDevice || !Filename)
    return E_FAIL;

  // Load and assemble the shader
  ID3DXBuffer *pCode;
  if(FAILED(hr=D3DXAssembleShaderFromFile(Filename, NULL, NULL, 0, &pCode, NULL)))
    return hr;
  if(FAILED(hr=pDevice->CreateVertexShader((DWORD*)pCode->GetBufferPointer(), ppShader)))
    return hr;
  pCode->Release();

  // Create the declaration interface if needed
  if(pElements && ppDecl)
    pDevice->CreateVertexDeclaration(pElements, ppDecl);

  // Return success
  return S_OK;
}


///////////////////////////////////////////////////////////
//
// Load mesh functions
//
///////////////////////////////////////////////////////////
HRESULT LoadMesh(D3DXMESHCONTAINER_EX **ppMesh,
                 IDirect3DDevice9 *pDevice,
                 char *Filename,
                 char *TexturePath,
                 DWORD NewFVF,
                 DWORD LoadFlags)
{
  ID3DXMesh *pLoadMesh = NULL;
  HRESULT hr;

  // Error checking
  if(!ppMesh || !pDevice || !Filename || !TexturePath)
    return E_FAIL;

  // Use system memory if converting FVF
  DWORD TempLoadFlags = LoadFlags;
  if(NewFVF)
    TempLoadFlags = D3DXMESH_SYSTEMMEM;

  // Load the mesh using D3DX routines
  ID3DXBuffer *MaterialBuffer = NULL, *AdjacencyBuffer = NULL;
  DWORD NumMaterials;
  if(FAILED(hr=D3DXLoadMeshFromX(Filename, TempLoadFlags,
                                 pDevice, &AdjacencyBuffer,
                                 &MaterialBuffer, NULL,
                                 &NumMaterials, &pLoadMesh)))
    return hr;

  // Convert to new FVF first as needed
  if(NewFVF) {
    ID3DXMesh *pTempMesh;

    // Use CloneMeshFVF to convert mesh
    if(FAILED(hr=pLoadMesh->CloneMeshFVF(LoadFlags, NewFVF, pDevice, &pTempMesh))) {
      ReleaseCOM(AdjacencyBuffer);
      ReleaseCOM(MaterialBuffer);
      ReleaseCOM(pLoadMesh);
      return hr;
    }

    // Free prior mesh and store new pointer
    ReleaseCOM(pLoadMesh);
    pLoadMesh = pTempMesh; pTempMesh = NULL;
  }

  // Allocate a D3DXMESHCONTAINER_EX structure
  D3DXMESHCONTAINER_EX *pMesh = new D3DXMESHCONTAINER_EX();
  *ppMesh = pMesh;

  // Store mesh name (filename), type, and mesh pointer
  pMesh->Name = strdup(Filename);
  pMesh->MeshData.Type = D3DXMESHTYPE_MESH;
  pMesh->MeshData.pMesh = pLoadMesh; pLoadMesh = NULL;

  // Store adjacency buffer
  DWORD AdjSize = AdjacencyBuffer->GetBufferSize();
  if(AdjSize) {
    pMesh->pAdjacency = new DWORD[AdjSize];
    memcpy(pMesh->pAdjacency, AdjacencyBuffer->GetBufferPointer(), AdjSize);
  }
  ReleaseCOM(AdjacencyBuffer);

  // Build material list
  if(!(pMesh->NumMaterials = NumMaterials)) {
    
    // Create a default material
    pMesh->NumMaterials = 1;
    pMesh->pMaterials   = new D3DXMATERIAL[1];
    pMesh->pTextures    = new IDirect3DTexture9*[1];

    ZeroMemory(pMesh->pMaterials, sizeof(D3DXMATERIAL));
    pMesh->pMaterials[0].MatD3D.Diffuse.r = 1.0f;
    pMesh->pMaterials[0].MatD3D.Diffuse.g = 1.0f;
    pMesh->pMaterials[0].MatD3D.Diffuse.b = 1.0f;
    pMesh->pMaterials[0].MatD3D.Diffuse.a = 1.0f;
    pMesh->pMaterials[0].MatD3D.Ambient   = pMesh->pMaterials[0].MatD3D.Diffuse;
    pMesh->pMaterials[0].MatD3D.Specular  = pMesh->pMaterials[0].MatD3D.Diffuse;
    pMesh->pMaterials[0].pTextureFilename = NULL;
    pMesh->pTextures[0]                   = NULL;

  } else {

    // Load the materials
    D3DXMATERIAL *Materials = (D3DXMATERIAL*)MaterialBuffer->GetBufferPointer();
    pMesh->pMaterials = new D3DXMATERIAL[pMesh->NumMaterials];
    pMesh->pTextures  = new IDirect3DTexture9*[pMesh->NumMaterials];

    for(DWORD i=0;i<pMesh->NumMaterials;i++) {
      pMesh->pMaterials[i].MatD3D = Materials[i].MatD3D;
      pMesh->pMaterials[i].MatD3D.Ambient = pMesh->pMaterials[i].MatD3D.Diffuse;

      // Load the texture if one exists
      pMesh->pTextures[i] = NULL;
      if(Materials[i].pTextureFilename) {
        char TextureFile[MAX_PATH];
        sprintf(TextureFile, "%s%s", TexturePath, 
                             Materials[i].pTextureFilename);
        D3DXCreateTextureFromFile(pDevice,
                                  TextureFile,
                                  &pMesh->pTextures[i]);
      }
    }
  }
  ReleaseCOM(MaterialBuffer);

  // Optimize the mesh for better attribute access
  pMesh->MeshData.pMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL);

  // Clear pMesh pointer just in case
  pMesh = NULL;

  return S_OK;
}

HRESULT LoadMesh(D3DXMESHCONTAINER_EX **ppMesh,
                 IDirect3DDevice9 *pDevice,
                 IDirectXFileData *pDataObj,
                 char *TexturePath,
                 DWORD NewFVF,
                 DWORD LoadFlags)
{
  ID3DXMesh *pLoadMesh = NULL;
  ID3DXSkinInfo *pSkin = NULL;
  HRESULT hr;

  // Error checking
  if(!ppMesh || !pDevice || !pDataObj || !TexturePath)
    return E_FAIL;

  // Use system memory if converting FVF
  DWORD TempLoadFlags = LoadFlags;
  if(NewFVF)
    TempLoadFlags = D3DXMESH_SYSTEMMEM;

  // Load the mesh using the D3DX skinned mesh interface
  ID3DXBuffer *MaterialBuffer = NULL, *AdjacencyBuffer = NULL;
  DWORD NumMaterials;
  if(FAILED(hr=D3DXLoadSkinMeshFromXof(pDataObj, TempLoadFlags,
                                       pDevice, &AdjacencyBuffer,
                                       &MaterialBuffer, NULL,
                                       &NumMaterials, &pSkin,
                                       &pLoadMesh)))
    return hr;

  // Free skin info if no bones
  if(pSkin && !pSkin->GetNumBones())
    ReleaseCOM(pSkin);

  // Convert to new FVF first as needed (not w/skinned models)
  if(NewFVF) {
    ID3DXMesh *pTempMesh = NULL;

    // Use CloneMeshFVF to convert mesh
    if(FAILED(hr=pLoadMesh->CloneMeshFVF(LoadFlags, NewFVF, pDevice, &pTempMesh))) {
      ReleaseCOM(pLoadMesh);
      ReleaseCOM(pSkin);
      ReleaseCOM(MaterialBuffer);
      ReleaseCOM(AdjacencyBuffer);
      return hr;
    }

    // Free prior mesh and store new pointer
    ReleaseCOM(pLoadMesh);
    pLoadMesh = pTempMesh; pTempMesh = NULL;
  }
 
  // Allocate a D3DXMESHCONTAINER_EX structure
  D3DXMESHCONTAINER_EX *pMesh = new D3DXMESHCONTAINER_EX();
  *ppMesh = pMesh;

  // Store mesh template name, type, and mesh pointers
  DWORD Size;
  pDataObj->GetName(NULL, &Size);
  if(Size) {
    pMesh->Name = new char[Size];
    pDataObj->GetName(pMesh->Name, &Size);
  }

⌨️ 快捷键说明

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