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

📄 direct3d.cpp

📁 用DirectX制作高级动画-[Advanced.Animation.with.DirectX]
💻 CPP
📖 第 1 页 / 共 3 页
字号:
  pMesh->MeshData.Type = D3DXMESHTYPE_MESH;
  pMesh->MeshData.pMesh = pLoadMesh; pLoadMesh = NULL;
  pMesh->pSkinInfo = pSkin; pSkin = NULL;

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

  // Create a duplicate mesh in case skinning is used
  if(pMesh->pSkinInfo)
    pMesh->MeshData.pMesh->CloneMeshFVF(0, //D3DXMESH_MANAGED, 
                                        pMesh->MeshData.pMesh->GetFVF(), 
                                        pDevice, &pMesh->pSkinMesh);

  // 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[0], 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,
                 D3DXFRAME_EX **ppFrame,
                 IDirect3DDevice9 *pDevice,
                 char *Filename,
                 char *TexturePath,
                 DWORD NewFVF,
                 DWORD LoadFlags)
{
  cXInternalParser Parser;

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

  // Set parser data
  Parser.m_pD3DDevice  = pDevice;
  Parser.m_TexturePath = TexturePath;
  Parser.m_NewFVF      = NewFVF;
  Parser.m_LoadFlags   = LoadFlags;
  Parser.m_Flags       = ((!ppMesh)?0:1) | ((!ppFrame)?0:2);

  // Clear mesh and frame pointers
  Parser.m_RootFrame   = NULL;
  Parser.m_RootMesh    = NULL;

  // Parse the file
  Parser.Parse(Filename);

  // Map the matrices to the frames and create an array of bone 
  // matrices, but only if user passed pointers to receive and 
  // the loader found some meshes and frames.
  if(ppMesh && ppFrame && Parser.m_RootMesh && Parser.m_RootFrame) {

    // Scan through all meshes
    D3DXMESHCONTAINER_EX *pMesh = Parser.m_RootMesh;
    while(pMesh) {

      // Does this mesh use skinning?
      if(pMesh->pSkinInfo) {

        // Get the number of bones
        DWORD NumBones = pMesh->pSkinInfo->GetNumBones();

        // Allocate the matrix pointers and bone matrices
        pMesh->ppFrameMatrices = new D3DXMATRIX*[NumBones];
        pMesh->pBoneMatrices   = new D3DXMATRIX[NumBones];

        // Match matrix pointers to frames
        for(DWORD i=0;i<NumBones;i++) {

          // Get bone name
          const char *BoneName = pMesh->pSkinInfo->GetBoneName(i);

          // Find matching name in frames
          D3DXFRAME_EX *pFrame = Parser.m_RootFrame->Find(BoneName);

          // Match frame to bone
          if(pFrame)
            pMesh->ppFrameMatrices[i] = &pFrame->matCombined;
          else
            pMesh->ppFrameMatrices[i] = NULL;
        }
      }

      // Go to next mesh
      pMesh = (D3DXMESHCONTAINER_EX*)pMesh->pNextMeshContainer;
    } 
  }

  // Copy the pointers into passed variables
  if(ppMesh) {
    // Assign mesh list pointer
    *ppMesh = Parser.m_RootMesh;
    Parser.m_RootMesh = NULL;
  } else {
    // Delete list of meshes in case any were loaded
    // and were not needed.
    delete Parser.m_RootMesh;
    Parser.m_RootMesh = NULL;
  }

  if(ppFrame) {
    // Assign frame hierarchy pointer
    *ppFrame = Parser.m_RootFrame;
    Parser.m_RootFrame = NULL;
  } else {
    // Delete frame hierarchy in case it was loaded
    // and it was not needed.
    delete Parser.m_RootFrame;
    Parser.m_RootFrame = NULL;
  }

  return S_OK;
}


///////////////////////////////////////////////////////////
//
// Update a skinned mesh
//
///////////////////////////////////////////////////////////
HRESULT UpdateMesh(D3DXMESHCONTAINER_EX *pMesh)
{
  // Error checking
  if(!pMesh)
    return E_FAIL;
  if(!pMesh->MeshData.pMesh || !pMesh->pSkinMesh || !pMesh->pSkinInfo)
    return E_FAIL;
  if(!pMesh->pBoneMatrices || !pMesh->ppFrameMatrices)
    return E_FAIL;

  // Copy the bone matrices over (must have been combined before call DrawMesh)
  for(DWORD i=0;i<pMesh->pSkinInfo->GetNumBones();i++) {

    // Start with bone offset matrix
    pMesh->pBoneMatrices[i] = (*pMesh->pSkinInfo->GetBoneOffsetMatrix(i));

    // Apply frame transformation
    if(pMesh->ppFrameMatrices[i])
      pMesh->pBoneMatrices[i] *= (*pMesh->ppFrameMatrices[i]);
  }

  // Lock the meshes' vertex buffers
  void *SrcPtr, *DestPtr;
  pMesh->MeshData.pMesh->LockVertexBuffer(D3DLOCK_READONLY, (void**)&SrcPtr);
  pMesh->pSkinMesh->LockVertexBuffer(0, (void**)&DestPtr);

  // Update the skinned mesh using provided transformations
  pMesh->pSkinInfo->UpdateSkinnedMesh(pMesh->pBoneMatrices, NULL, SrcPtr, DestPtr);

  // Unlock the meshes vertex buffers
  pMesh->pSkinMesh->UnlockVertexBuffer();
  pMesh->MeshData.pMesh->UnlockVertexBuffer();

  // Return success
  return S_OK;
}


///////////////////////////////////////////////////////////
//
// Draw mesh functions
//
///////////////////////////////////////////////////////////
HRESULT DrawMesh(D3DXMESHCONTAINER_EX *pMesh)
{
  IDirect3DDevice9 *pD3DDevice;
  DWORD LastState, OldAlphaState, OldSrcBlend, OldDestBlend;

  // Error checking
  if(!pMesh)
    return E_FAIL;
  if(!pMesh->MeshData.pMesh)
    return E_FAIL;
  if(!pMesh->NumMaterials || !pMesh->pMaterials)
    return E_FAIL;

  // Get the device interface
  pMesh->MeshData.pMesh->GetDevice(&pD3DDevice);

  // Release vertex shader if being used
  pD3DDevice->SetVertexShader(NULL);
  pD3DDevice->SetVertexDeclaration(NULL);

  // Save render states
  pD3DDevice->GetRenderState(D3DRS_ALPHABLENDENABLE, &OldAlphaState);
  pD3DDevice->GetRenderState(D3DRS_SRCBLEND, &OldSrcBlend);
  pD3DDevice->GetRenderState(D3DRS_DESTBLEND, &OldDestBlend);
  LastState = OldAlphaState;

  // Setup pointer for mesh to draw, either regular or skinned
  ID3DXMesh *pDrawMesh = (!pMesh->pSkinMesh)?pMesh->MeshData.pMesh:pMesh->pSkinMesh;

  // Look through all subsets
  for(DWORD i=0;i<pMesh->NumMaterials;i++) {

    // Set material and texture
    pD3DDevice->SetMaterial(&pMesh->pMaterials[i].MatD3D);
    pD3DDevice->SetTexture(0, pMesh->pTextures[i]);

    // Enable or disable alpha blending per material
    if(pMesh->pMaterials[i].MatD3D.Diffuse.a != 1.0f) {
      if(LastState != TRUE) {
        LastState = TRUE;
        pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
        pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);//SRCCOLOR);
        pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);
      }
    } else {
      if(LastState != FALSE) {
        LastState = FALSE;
        pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
      }
    }

    // Draw the mesh subset
    pDrawMesh->DrawSubset(i);
  }

  // Restore alpha blending states
  if(LastState != OldAlphaState) {
    pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, OldAlphaState);
    pD3DDevice->SetRenderState(D3DRS_SRCBLEND, OldSrcBlend);
    pD3DDevice->SetRenderState(D3DRS_DESTBLEND, OldDestBlend);
  }

  // Make sure to release the device object!
  pD3DDevice->Release();

  // Return success
  return S_OK;
}

HRESULT DrawMesh(D3DXMESHCONTAINER_EX *pMesh,
                 IDirect3DVertexShader9 *pShader, 
                 IDirect3DVertexDeclaration9 *pDecl)
{
  IDirect3DDevice9 *pD3DDevice;
  DWORD LastState, OldAlphaState, OldSrcBlend, OldDestBlend;

  // Error checking
  if(!pMesh || !pShader || !pDecl)
    return E_FAIL;
  if(!pMesh->MeshData.pMesh)
    return E_FAIL;
  if(!pMesh->NumMaterials || !pMesh->pMaterials)
    return E_FAIL;

  // Get the device interface
  pMesh->MeshData.pMesh->GetDevice(&pD3DDevice);

  // Save render states
  pD3DDevice->GetRenderState(D3DRS_ALPHABLENDENABLE, &OldAlphaState);
  pD3DDevice->GetRenderState(D3DRS_SRCBLEND, &OldSrcBlend);
  pD3DDevice->GetRenderState(D3DRS_DESTBLEND, &OldDestBlend);
  LastState = OldAlphaState;

  // Get mesh buffer pointers
  IDirect3DVertexBuffer9 *pVB = NULL;
  IDirect3DIndexBuffer9 *pIB  = NULL;
  pMesh->MeshData.pMesh->GetVertexBuffer(&pVB);
  pMesh->MeshData.pMesh->GetIndexBuffer(&pIB);

  // Get attribute table
  DWORD NumAttributes;
  D3DXATTRIBUTERANGE *pAttributes = NULL;
  pMesh->MeshData.pMesh->GetAttributeTable(NULL, &NumAttributes);
  pAttributes = new D3DXATTRIBUTERANGE[NumAttributes];
  pMesh->MeshData.pMesh->GetAttributeTable(pAttributes, &NumAttributes);

  // Use the vertex shader interface passed
  pD3DDevice->SetFVF(NULL);
  pD3DDevice->SetVertexShader(pShader);
  pD3DDevice->SetVertexDeclaration(pDecl);

  // Set stream sources
  pD3DDevice->SetStreamSource(0, pVB, 0, D3DXGetFVFVertexSize(pMesh->MeshData.pMesh->GetFVF()));
  pD3DDevice->SetIndices(pIB);

  // Go through each attribute group and render
  for(DWORD i=0;i<NumAttributes;i++) {

    if(pAttributes[i].FaceCount) {

      // Get material number
      DWORD MatNum = pAttributes[i].AttribId;

      // Set texture
      pD3DDevice->SetTexture(0, pMesh->pTextures[MatNum]);

      // Enable or disable alpha blending per material
      if(pMesh->pMaterials[i].MatD3D.Diffuse.a != 1.0f) {
        if(LastState != TRUE) {
          LastState = TRUE;
          pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
          pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);//SRCCOLOR);
          pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);
        }
      } else {

⌨️ 快捷键说明

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