关于DirectX高级动画书中使用的9.0bsdk的升级说明

在《Advanced.Animation.with.DirectX》DirectX开发游戏高级动画书中的代码例子都使用了9.0B版本的sdk,现如今的新入行的程序员很少有人再去使用vc6.0 ,大部分人都使用的是9.0c版本的sdk,所以导致编译出现错误:

error C2664: 'D3DXLoadSkinMeshFromXof' : cannot convert parameter 1 from 'IDirectXFileData *' to 'LPD3DXFILEDATA'

 

要想使用vs2005和9.0c

那么需要修改几个地方:

1、搜索所有的IDirectXFileData 替换成ID3DXFileData,添加D3dx9xof.h

替换所有的

IDirectXFile成ID3DXFile

IDirectXFileEnumObject --   ID3DXFileEnumObject

DirectXFileCreate                D3DXFileCreate

 

 

 

但是ID3DXFileData 没有GetData,GetNextObject,AddDataReference等方法.

判断是否引用的改成了IsReference方法.

而获取子信息由原来的一个函数换成了这两个GetChild,GetChildren

下面是我经过改动之后代码......帮那些正在学的人少走一条湾路......

#ifndef _DIRECT3D_H_
#define _DIRECT3D_H_

#include <stdio.h>
#include <windows.h>
#include "d3d9.h"
#include "d3dx9.h"
#include "dxfile.h"
#include "XFile.h"
#include "D3dx9xof.h"

#define ReleaseCOM(x) { if(x!=NULL) x->Release(); x=NULL; }

// Declare an extended version of D3DXFRAME
// that contains a constructor and destructor
// as well as a combined transformation matrix
struct D3DXFRAME_EX : D3DXFRAME
{
  D3DXMATRIX matCombined;   // Combined matrix
  D3DXMATRIX matOriginal;   // Original transformation from .X
 
  D3DXFRAME_EX()
  {
    Name = NULL;
    pMeshContainer = NULL;
    pFrameSibling = pFrameFirstChild = NULL;
    D3DXMatrixIdentity(&matCombined);
    D3DXMatrixIdentity(&matOriginal);
    D3DXMatrixIdentity(&TransformationMatrix);
  }

  ~D3DXFRAME_EX()
  {
    delete [] Name;          Name = NULL;
    delete pFrameSibling;    pFrameSibling = NULL;
    delete pFrameFirstChild; pFrameFirstChild = NULL;
  }

  // Function to scan hierarchy for matching frame name
  D3DXFRAME_EX *Find(const char *FrameName)
  {
    D3DXFRAME_EX *pFrame, *pFramePtr;

    // Return this frame instance if name matched
    if(Name && FrameName && !strcmp(FrameName, Name))
      return this;

    // Scan siblings
    if((pFramePtr = (D3DXFRAME_EX*)pFrameSibling)) {
      if((pFrame = pFramePtr->Find(FrameName)))
        return pFrame;
    }

    // Scan children
    if((pFramePtr = (D3DXFRAME_EX*)pFrameFirstChild)) {
      if((pFrame = pFramePtr->Find(FrameName)))
        return pFrame;
    }

    // Return none found
    return NULL;
  }

  // Reset transformation matrices to originals
  void Reset()
  {
    // Copy original matrix
    TransformationMatrix = matOriginal;

    // Reset sibling frames
    D3DXFRAME_EX *pFramePtr;
    if((pFramePtr = (D3DXFRAME_EX*)pFrameSibling))
      pFramePtr->Reset();

    // Reset child frames
    if((pFramePtr = (D3DXFRAME_EX*)pFrameFirstChild))
      pFramePtr->Reset();
  }

  // Function to combine matrices in frame hiearchy
  void UpdateHierarchy(D3DXMATRIX *matTransformation = NULL)
  {
    D3DXFRAME_EX *pFramePtr;
    D3DXMATRIX matIdentity;

    // Use an identity matrix if none passed
    if(!matTransformation) {
      D3DXMatrixIdentity(&matIdentity);
      matTransformation = &matIdentity;
    }

    // Combine matrices w/supplied transformation matrix
    matCombined = TransformationMatrix * (*matTransformation);

    // Combine w/sibling frames
    if((pFramePtr = (D3DXFRAME_EX*)pFrameSibling))
      pFramePtr->UpdateHierarchy(matTransformation);

    // Combine w/child frames
    if((pFramePtr = (D3DXFRAME_EX*)pFrameFirstChild))
      pFramePtr->UpdateHierarchy(&matCombined);
  }

  void Count(DWORD *Num)
  {
    // Error checking
    if(!Num)
      return;

    // Increase count of frames
    (*Num)+=1;

    // Process sibling frames
    D3DXFRAME_EX *pFrame;
    if((pFrame=(D3DXFRAME_EX*)pFrameSibling))
      pFrame->Count(Num);

    // Process child frames
    if((pFrame=(D3DXFRAME_EX*)pFrameFirstChild))
      pFrame->Count(Num);
  }
};

// Declare an extended version of D3DXMESHCONTAINER
// that contains a constructor and destructor
// as well as an array of textures, a mesh object
// that contains the generated skin mesh, and
// matrices that map to the frame hierarchy's and
// for updating bones.
struct D3DXMESHCONTAINER_EX : D3DXMESHCONTAINER
{
  IDirect3DTexture9 **pTextures;
  ID3DXMesh          *pSkinMesh;

  D3DXMATRIX        **ppFrameMatrices;
  D3DXMATRIX         *pBoneMatrices;

  D3DXMESHCONTAINER_EX()
  {
    Name               = NULL;
    MeshData.pMesh     = NULL;
    pMaterials         = NULL;
    pEffects           = NULL;
    NumMaterials       = 0;
    pAdjacency         = NULL;
    pSkinInfo          = NULL;
    pNextMeshContainer = NULL;
    pTextures          = NULL;
    pSkinMesh          = NULL;
    ppFrameMatrices    = NULL;
    pBoneMatrices      = NULL;
  }

  ~D3DXMESHCONTAINER_EX()
  {
    if(pTextures && NumMaterials) {
      for(DWORD i=0;i<NumMaterials;i++)
        ReleaseCOM(pTextures[i]);
    }
    delete [] pTextures;       pTextures = NULL;
    NumMaterials = 0;

    delete [] Name;            Name = NULL;
    delete [] pMaterials;      pMaterials = NULL;
    delete pEffects;           pEffects = NULL;

    delete [] pAdjacency;      pAdjacency = NULL;
    delete [] ppFrameMatrices; ppFrameMatrices = NULL;
    delete [] pBoneMatrices;   pBoneMatrices = NULL;

    ReleaseCOM(MeshData.pMesh);
    ReleaseCOM(pSkinInfo);
    ReleaseCOM(pSkinMesh);

    delete pNextMeshContainer; pNextMeshContainer = NULL;
  }

  D3DXMESHCONTAINER_EX *Find(char *MeshName)
  {
    D3DXMESHCONTAINER_EX *pMesh, *pMeshPtr;

    // Return this mesh instance if name matched
    if(Name && MeshName && !strcmp(MeshName, Name))
      return this;

    // Scan next in list
    if((pMeshPtr = (D3DXMESHCONTAINER_EX*)pNextMeshContainer)) {
      if((pMesh = pMeshPtr->Find(MeshName)))
        return pMesh;
    }

    // Return none found
    return NULL;
  }
};

// Declare an internal .X file parser class for loading meshes and frames
class cXInternalParser
{
  public:
    // Information passed from calling function
    IDirect3DDevice9     *m_pD3DDevice;
    char                 *m_TexturePath;
    DWORD                 m_NewFVF;
    DWORD                 m_LoadFlags;

    // Flags for which data to load
    // 1 = mesh, 2 = frames, 3= both
    DWORD                 m_Flags;

    // Hierarchies used during loading
    D3DXMESHCONTAINER_EX *m_RootMesh;
    D3DXFRAME_EX         *m_RootFrame;

  protected:
    // Function called for every template found
    BOOL ParseObject(ID3DXFileData  *pDataObj,
                       ID3DXFileData  *pParentDataObj,
                       DWORD Depth,
                       void **Data, BOOL Reference);

    // Function called to enumerate child templates
    BOOL ParseChildObjects(ID3DXFileData *pDataObj,
                             DWORD Depth, void **Data,
                             BOOL ForceReference = FALSE);

  public:
    // Constructor and destructor
    cXInternalParser();
    ~cXInternalParser();

    // Function to start parsing an .X file
    BOOL Parse(char *Filename, void **Data = NULL);

    // Functions to help retrieve template information
    const GUID *GetObjectGUID(ID3DXFileData *pDataObj);
    char *GetObjectName(ID3DXFileData *pDataObj);
    void *GetObjectData(ID3DXFileData *pDataObj, DWORD *Size);
};


// Initialize D3D
HRESULT InitD3D(IDirect3D9 **ppD3D,
                IDirect3DDevice9 **ppD3DDevice,
                HWND hWnd, BOOL ForceWindowed = FALSE,
                BOOL MultiThreaded = FALSE);

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

// Load a single mesh from an .X file (compact multiple meshes into one)
HRESULT LoadMesh(D3DXMESHCONTAINER_EX **ppMesh,
                 IDirect3DDevice9 *pDevice,
                 char *Filename,
                 char *TexturePath = ".//",
                 DWORD NewFVF = 0,
                 DWORD LoadFlags = D3DXMESH_SYSTEMMEM);

// Load a single mesh (regular or skinned) from a mesh template
HRESULT LoadMesh(D3DXMESHCONTAINER_EX **ppMesh,
                 IDirect3DDevice9 *pDevice,
                 ID3DXFileData *pDataObj,
                 char *TexturePath = ".//",
                 DWORD NewFVF = 0,
                 DWORD LoadFlags = D3DXMESH_SYSTEMMEM);

// Load all meshes and frames from an .X file
HRESULT LoadMesh(D3DXMESHCONTAINER_EX **ppMesh,
                 D3DXFRAME_EX **ppFrame,
                 IDirect3DDevice9 *pDevice,
                 char *Filename,
                 char *TexturePath = ".//",
                 DWORD NewFVF = 0,
                 DWORD LoadFlags = D3DXMESH_SYSTEMMEM);

// Update a skinned mesh
HRESULT UpdateMesh(D3DXMESHCONTAINER_EX *pMesh);

// Draw the first mesh in a linked list of objects
HRESULT DrawMesh(D3DXMESHCONTAINER_EX *pMesh);

// Draw the first mesh in a linked list of objects
// using the specified vertex shader and declaration
HRESULT DrawMesh(D3DXMESHCONTAINER_EX *pMesh,
                 IDirect3DVertexShader9 *pShader,
                 IDirect3DVertexDeclaration9 *pDecl);

// Draw all meshes in a linked list of objects
HRESULT DrawMeshes(D3DXMESHCONTAINER_EX *pMesh);

// Draw all meshes in a linked list of objects
// using the specified vertex shader and declaration
HRESULT DrawMeshes(D3DXMESHCONTAINER_EX *pMesh,
                   IDirect3DVertexShader9 *pShader,
                   IDirect3DVertexDeclaration9 *pDecl);

#endif

 

 

#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,
                 ID3DXFileData  *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);
  }
  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 {
        if(LastState != FALSE) {
          LastState = FALSE;
          pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
        }
      }

      // Draw the mesh subset
      pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,
                                       pAttributes[i].VertexStart,
                                       pAttributes[i].VertexCount,
                                       pAttributes[i].FaceStart * 3,
                                       pAttributes[i].FaceCount);
    }
  }

  // Clear stream uses
  pD3DDevice->SetStreamSource(0, NULL, 0, 0);
  pD3DDevice->SetIndices(NULL);

  // Free resources
  ReleaseCOM(pVB);
  ReleaseCOM(pIB);
  delete [] pAttributes;

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

  // Release vertex shader and declaration mapping
  pD3DDevice->SetVertexShader(NULL);
  pD3DDevice->SetVertexDeclaration(NULL);

  return S_OK;
}

HRESULT DrawMeshes(D3DXMESHCONTAINER_EX *pMesh)
{
  D3DXMESHCONTAINER_EX *MeshPtr = pMesh;

  // Loop through all meshes in list
  while(MeshPtr) {

    // Draw mesh, returning on error
    HRESULT hr = DrawMesh(MeshPtr);
    if(FAILED(hr))
      return hr;

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

  // Return success
  return S_OK;
}

HRESULT DrawMeshes(D3DXMESHCONTAINER_EX *pMesh,
                   IDirect3DVertexShader9 *pShader,
                   IDirect3DVertexDeclaration9 *pDecl)
{
  D3DXMESHCONTAINER_EX *MeshPtr = pMesh;

  // Loop through all meshes in list
  while(MeshPtr) {

    // Draw mesh, returning on error
    HRESULT hr = DrawMesh(MeshPtr, pShader, pDecl);
    if(FAILED(hr))
      return hr;

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

  // Return success
  return S_OK;
}

///
//
// Generic .X parser class code
//
///
cXInternalParser::cXInternalParser()
{
  m_pD3DDevice  = NULL;
  m_TexturePath = NULL;
  m_Flags       = 0;
  m_RootMesh    = NULL;
  m_RootFrame   = NULL;
}

cXInternalParser::~cXInternalParser()
{
  delete m_RootMesh;  m_RootMesh  = NULL;
  delete m_RootFrame; m_RootFrame = NULL;
}

BOOL cXInternalParser::Parse(char *Filename, void **Data)
{
  ID3DXFile           *pDXFile = NULL;
  ID3DXFileEnumObject *pDXEnum = NULL;
  ID3DXFileData       *pDXData = NULL;

  // Error checking
  if(Filename == NULL)
    return FALSE;

  // Create the file object
  if(FAILED(D3DXFileCreate(&pDXFile)))
    return FALSE;

  // Register the common templates
  if(FAILED(pDXFile->RegisterTemplates(                       /
                     (LPVOID)D3DRM_XTEMPLATES,                /
                     D3DRM_XTEMPLATE_BYTES))) {
    pDXFile->Release();
    return FALSE;
  }

  // Create an enumeration object
  if(FAILED(pDXFile->CreateEnumObject((LPVOID)Filename,       /
                                      DXFILELOAD_FROMFILE,    /
                                      &pDXEnum))) {
    pDXFile->Release();
    return FALSE;
  }
 
  // Loop through all top-level objects, breaking on errors
  //BOOL ParseResult;
  //while(SUCCEEDED(pDXEnum->GetNextDataObject(&pDXData))) {
  //  ParseResult = ParseObject(pDXData, NULL, 0, Data, FALSE);
  //  ReleaseCOM(pDXData);
  //  if(ParseResult == FALSE)
  //    break;
  //}

  SIZE_T num_child;
  pDXEnum->GetChildren(&num_child);
  BOOL ParseResult;
  for(SIZE_T i = 0; i < num_child; i++)
  {
   if(FAILED(pDXEnum->GetChild(i, &pDXData)))
    return NULL;  
   ParseResult = ParseObject(pDXData, NULL,0,Data,FALSE);
   ReleaseCOM(pDXData);
   if(ParseResult == FALSE)
    break;
  }


  // Release used COM objects
  ReleaseCOM(pDXEnum);
  ReleaseCOM(pDXFile);

  return TRUE;
}

BOOL cXInternalParser::ParseObject(ID3DXFileData *pDataObj,
                                     ID3DXFileData *pParentDataObj,
                                     DWORD Depth,
                                     void **Data, BOOL Reference)
{
  const GUID *Type = GetObjectGUID(pDataObj);

  // Process templates based on their type

  // Build on to frame hierarchy (ony non-referenced frames)
  if(*Type == TID_D3DRMFrame && Reference == FALSE && m_Flags & 2) {

    // Allocate a frame
    D3DXFRAME_EX *pFrame = new D3DXFRAME_EX();

    // Get the frame's name (if any)
    pFrame->Name = GetObjectName(pDataObj);

    // Link frame into hierarchy
    if(Data == NULL) {
      // Link as sibling of root
      pFrame->pFrameSibling = m_RootFrame;
      m_RootFrame = pFrame; pFrame = NULL;
      Data = (void**)&m_RootFrame;
    } else {
      // Link as child of supplied frame
      D3DXFRAME_EX *pFramePtr = (D3DXFRAME_EX*)*Data;
      pFrame->pFrameSibling = pFramePtr->pFrameFirstChild;
      pFramePtr->pFrameFirstChild = pFrame; pFrame = NULL;
      Data = (void**)&pFramePtr->pFrameFirstChild;
    }
  }

  // Set a frame transformation matrix
  if(*Type == TID_D3DRMFrameTransformMatrix && Reference == FALSE && m_Flags & 2 && Data) {

    D3DXFRAME_EX *Frame = (D3DXFRAME_EX*)*Data;
    if(Frame) {
      Frame->TransformationMatrix = *(D3DXMATRIX*)GetObjectData(pDataObj, NULL);
      Frame->matOriginal = Frame->TransformationMatrix;
    }
  }

  // Load a mesh (skinned or regular)
  if(*Type == TID_D3DRMMesh && m_Flags & 1) {

    // Only load non-referenced skin meshes into memory
    if(Reference == FALSE) {
     
      // Load the mesh using the data object load method
      D3DXMESHCONTAINER_EX *pMesh = NULL;
      LoadMesh(&pMesh, m_pD3DDevice, pDataObj, m_TexturePath, m_NewFVF, m_LoadFlags);

      // Link mesh to head of list of meshes
      if(pMesh) {
        pMesh->pNextMeshContainer = m_RootMesh;
        m_RootMesh = pMesh; pMesh = NULL;

        // Link mesh to frame if needed
        if(Data) {
          D3DXFRAME_EX *pFrame = (D3DXFRAME_EX*)*Data;
          if(m_Flags & 2 && pFrame)
            pFrame->pMeshContainer = m_RootMesh;
        }
      }
    } else {

      // If referenced, then check if wanting to link to frame
      if(Data) {
        D3DXFRAME_EX *pFrame = (D3DXFRAME_EX*)*Data;
        if(m_Flags & 2 && m_RootMesh && pFrame) {

          // Get name of mesh reference to link to
          char *Name = GetObjectName(pDataObj);
          if(Name) {
            // Find matching mesh by name and store result
            pFrame->pMeshContainer = m_RootMesh->Find(Name);

            // Clear name
            delete [] Name; Name = NULL;
          }
        }
      }
    }
  }

  // Parse child templates
  return ParseChildObjects(pDataObj, Depth, Data, Reference);
}

BOOL cXInternalParser::ParseChildObjects(ID3DXFileData *pDataObj,
                                           DWORD Depth, void **Data,
                                           BOOL ForceReference)
{
 ID3DXFileData        *pSubObj  = NULL;
 SIZE_T num_child;   
 BOOL                       ParseResult = TRUE;
 pDataObj->GetChildren(&num_child);  

 for(SIZE_T j = 0; j < num_child; j++)  
 {  
  pDataObj->GetChild(j, &pSubObj);  
  if(pSubObj->IsReference()){
   ForceReference = true;
  }
  ParseResult = ParseObject(pSubObj,pDataObj,Depth+1, Data,ForceReference);
  ReleaseCOM(pSubObj);
  // Return on parsing failure
  if(ParseResult == FALSE)
   return FALSE;
 }


  IDirectXFileObject        *pSubObj  = NULL;
  ID3DXFileData          *pSubData = NULL;
  IDirectXFileDataReference *pDataRef = NULL;
  BOOL                       ParseResult = TRUE;

  // Scan for embedded templates
  while(SUCCEEDED(pDataObj->GetNextObject(&pSubObj))) {

    // Process embedded references
    if(SUCCEEDED(pSubObj->QueryInterface(
                              IID_IDirectXFileDataReference,
                              (void**)&pDataRef))) {

      // Resolve the data object
      if(SUCCEEDED(pDataRef->Resolve(&pSubData))) {

        // Parse the object, remembering the return code
        ParseResult = ParseObject(pSubData, pDataObj, Depth+1, Data, TRUE);
        ReleaseCOM(pSubData);
      }
      ReleaseCOM(pDataRef);

      // Return on parsing failure
      if(ParseResult == FALSE)
        return FALSE;
    } else

    // Process non-referenced embedded templates
    if(SUCCEEDED(pSubObj->QueryInterface(
                              IID_IDirectXFileData,
                              (void**)&pSubData))) {

      // Parse the object, remembering the return code
      ParseResult = ParseObject(pSubData, pDataObj, Depth+1, Data, ForceReference);
      ReleaseCOM(pSubData);
    }

    // Release the data object
    ReleaseCOM(pSubObj);

    // Return on parsing failure
    if(ParseResult == FALSE)
      return FALSE;
  }

  return TRUE;
}

const GUID *cXInternalParser::GetObjectGUID(ID3DXFileData *pDataObj)
{
  GUID*  Type = new GUID; 

  // Error checking
  if(pDataObj == NULL)
    return NULL;

  // Get the template type
  if(FAILED(pDataObj->GetType(Type)))
    return NULL;

  return Type;
}

char *cXInternalParser::GetObjectName(ID3DXFileData *pDataObj)
{
  char  *Name = NULL;
  DWORD  Size = 0;

  // Error checking
  if(pDataObj == NULL)
    return NULL;

  // Get the template name (if any)
  if(FAILED(pDataObj->GetName(NULL, &Size)))
    return NULL;

  // Allocate a name buffer and retrieve name
  if(Size) {
    if((Name = new char[Size]) != NULL)
      pDataObj->GetName(Name, &Size);
  }

  return Name;
}

void *cXInternalParser::GetObjectData(ID3DXFileData *pDataObj,
                                DWORD *Size)
{
  void *TemplateData;
  SIZE_T TemplateSize=0;

  // Error checking
  if(pDataObj == NULL)
    return NULL;

  // Get a data pointer to template
  //pDataObj->GetData(NULL, &TemplateSize, (PVOID*)&TemplateData);

  pDataObj->Lock(&TemplateSize,(LPCVOID*)(VOID **)&TemplateData);
  if (NULL==TemplateData)
  {
   return NULL;
  }
  // Save size if needed
  if(Size != NULL)
    *Size = TemplateSize;

  return TemplateData;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值