游戏开发论坛

 找回密码
 立即注册
搜索
查看: 1847|回复: 4

请教达人~~~关于骨骼动画的问题。

[复制链接]

23

主题

47

帖子

47

积分

注册会员

Rank: 2

积分
47
发表于 2009-2-25 00:53:00 | 显示全部楼层 |阅读模式
用SDK中的skinmesh的框架,它使用D3DXLoadMeshHierarchyFromX从.x文件中读的信息,但是我还需要.x文件中的mesh信息,其他例子是用D3DXLoadMeshFromX读.x文件得到的ID3DXMesh* g_pMesh这个接口接着用g_pMesh->LockVertexBuffer,,,,,,

我想用D3DXLoadMeshHierarchyFromX函数后.x中的mesh信息应该已经读进去了吧,我应该怎么才能得到ID3DXMesh* 这个接口指针呢?

请指点一下,,,谢谢

19

主题

638

帖子

638

积分

高级会员

Rank: 4

积分
638
发表于 2009-2-25 20:08:00 | 显示全部楼层

Re:请教达人~~~关于骨骼动画的问题。

D3DXLoadMeshHierarchyFromX得到的是没有合并的原始场景结构,是一个Frame的树型结构,mesh挂在里面的一些frame上

34

主题

657

帖子

672

积分

高级会员

Rank: 4

积分
672
发表于 2009-2-26 10:40:00 | 显示全部楼层

Re:请教达人~~~关于骨骼动画的问题。

www.gamedev.net上有关于如何解析.x文件的文章,还有源代码,参考一下自己解析也行。

0

主题

769

帖子

1052

积分

金牌会员

Rank: 6Rank: 6

积分
1052
发表于 2009-2-27 17:08:00 | 显示全部楼层

Re:请教达人~~~关于骨骼动画的问题。

//cMesh------------------------------------------------------------------------------------------------------------------
cMesh::cMesh()
{
        m_Graphics = NULL;
        m_NumMeshes = 0;
        m_Meshes = NULL;
        m_NumFrames = 0;
        m_Frames = NULL;

        m_Min.x = m_Min.y = m_Min.z = m_Max.x = m_Max.y = m_Max.z = 0.0f;
        m_Radius = 0.0f;
}

cMesh::~cMesh()
{
         Free();
}

BOOL cMesh::IsLoaded()
{
        if(m_Meshes != NULL && m_Frames != NULL)
                return TRUE;
        return FALSE;
}

HRESULT cMesh:oad(cGraphics *Graphics,char *Filename, char *TexturePath)
{
        ID3DXFile           *pDXFile = NULL;
        ID3DXFileEnumObject *pDXEnum = NULL;
        ID3DXFileData       *pDXData = NULL;
        sFrame                 *TempFrame, *FramePtr;
        sMesh                  *Mesh;

        DWORD                                dsize;

        // Free prior mesh object data
        Free();

        // Error checking
        if((m_Graphics = Graphics) == NULL || Filename == NULL)
                return E_FAIL;

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

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

        // Create an enumeration object
        if(FAILED(pDXFile->CreateEnumObject((LPVOID)Filename, DXFILELOAD_FROMFILE, &pDXEnum)))
        {
                pDXFile->Release();
                return E_FAIL;
        }

        // Create a temporary frame
        TempFrame = new sFrame();

        // Loop through all objects looking for the frames and meshes
        if(SUCCEEDED(pDXEnum->GetChildren(&dsize)))
        {
                for(DWORD i=0;i<dsize;i++)
                {
                        pDXEnum->GetChild(i,&pDXData);
                        ParseXFileData(pDXData, TempFrame,TexturePath);
                        ReleaseCOM(pDXData);
                }
        }

        // See if we should keep the tempframe as root
        if(TempFrame->MeshList != NULL)
        {
                m_Frames = TempFrame;
                m_Frames->Name = new char[7];
                strcpy(m_Frames->Name, "%ROOT%");
        }
        else
        {
    // Assign the root frame and release temporary frame
                m_Frames = TempFrame->Child;
                FramePtr = m_Frames;
                while(FramePtr != NULL)
                {
                        FramePtr-&gtarent = NULL;
                        FramePtr = FramePtr->Sibling;
                }
                TempFrame->Child = NULL;
                delete TempFrame;
        }
        // Match frames to bones (for matrices)
        MapFramesToBones(m_Frames);

        // Calculate bounding box and sphere
        if((Mesh = m_Meshes) != NULL)
        {
                while(Mesh != NULL)
                {
                        m_Min.x = min(m_Min.x, Mesh->m_Min.x);
                        m_Min.y = min(m_Min.y, Mesh->m_Min.y);
                        m_Min.z = min(m_Min.z, Mesh->m_Min.z);
                        m_Max.x = max(m_Max.x, Mesh->m_Max.x);
                        m_Max.y = max(m_Max.y, Mesh->m_Max.y);
                        m_Max.z = max(m_Max.z, Mesh->m_Max.z);
                        m_Radius = max(m_Radius, Mesh->m_Radius);

                        Mesh = Mesh->m_Next;
                }
        }
        return S_OK;
}

void cMesh:arseXFileData(ID3DXFileData *pDataObj,sFrame *ParentFrame,char *TexturePath)
{       
        ID3DXFileData        *pSubObj  = NULL;

        GUID  Type;
        char       *Name = NULL;
        DWORD       Size;
        sFrame     *SubFrame = NULL;
        char        Path[MAX_PATH];

        sFrame     *Frame = NULL;
        D3DXMATRIX *FrameMatrix = NULL;

        sMesh         *Mesh = NULL;
        ID3DXBuffer   *MaterialBuffer = NULL;
        D3DXMATERIAL  *Materials = NULL;
        ID3DXBuffer   *Adjacency = NULL;
        DWORD         *AdjacencyIn = NULL;
        DWORD                  *AdjacencyOut = NULL;

        DWORD                i;
        DWORD       dSize;
        BYTE                **Ptr;
        LPCVOID                Buffer;

        D3DXMATRIX Matrix;
       

        if(FAILED(pDataObj->GetType(&Type)))
        {
                return;
        }

        // Get the template name (if any)
        if(FAILED(pDataObj->GetName(NULL, &Size)))
                return;
        if(Size)
        {
                if((Name = new char[Size]) != NULL)
                        pDataObj->GetName(Name, &Size);
        }

        // Give template a default name if none found
        if(Name == NULL)
        {
                if((Name = new char[9]) == NULL)
                        return;
                strcpy(Name, "$NoName$");
        }

        // Set sub frame
        SubFrame = ParentFrame;

         // Process the templates

        // Frame
        if(Type == TID_D3DRMFrame)
        {
                // Create a new frame structure
                Frame = new sFrame();

                // Store the name
                Frame->Name = Name;
                Name = NULL;

                // Add to parent frame
                Frame->Parent = ParentFrame;
                Frame->Sibling = ParentFrame->Child;
                ParentFrame->Child = Frame;

                // Increase frame count
                m_NumFrames++;

                // Set sub frame parent
                SubFrame = Frame;
        }

        if(Type == TID_D3DRMFrameTransformMatrix&&pDataObj)
        {
                dSize = 0;
                Buffer = NULL;
                if(FAILED(pDataObj->Lock( &dSize, &Buffer )))
                        return ;
                if( dSize == sizeof( D3DXMATRIX ) )
        {
                        memcpy( &SubFrame->TransformationMatrix, Buffer, dSize );
            pDataObj->Unlock();
            SubFrame->matOriginal = SubFrame->TransformationMatrix;
         }
        }

        if(Type == TID_D3DRMMesh)
        {// See if mesh already loaded
                if(m_Meshes == NULL || m_Meshes->FindMesh(Name) == NULL)
                {// Create a new mesh structure
                        Mesh = new sMesh();
                // Store the name
                        Mesh->m_Name = Name;
                        Name = NULL;
                // Load mesh data
                        if(FAILED(D3DXLoadSkinMeshFromXof(pDataObj, 0,
                  m_Graphics->GetDevice(),
                  &Adjacency,
                  &MaterialBuffer, NULL, &Mesh->m_NumMaterials,
                  &Mesh->m_SkinInfo,
                  &Mesh->m_Mesh)))
                        {
                                delete Mesh;
                                return;
                        }
                        // Calculate the bounding box and sphere
                        if(SUCCEEDED(Mesh->m_Mesh->LockVertexBuffer(D3DLOCK_READONLY, (void**)&Ptr)))
                        {
                                D3DXComputeBoundingBox((D3DXVECTOR3*)Ptr, Mesh->m_Mesh->GetNumVertices(),
                                Mesh->m_Mesh->GetNumBytesPerVertex(), &Mesh->m_Min, &Mesh->m_Max);

                                D3DXComputeBoundingSphere((D3DXVECTOR3*)Ptr, Mesh->m_Mesh->GetNumVertices(),
                                Mesh->m_Mesh->GetNumBytesPerVertex(),
                                &D3DXVECTOR3(0.0f,0.0f,0.0f), &Mesh->m_Radius);

                                Mesh->m_Mesh->UnlockVertexBuffer();
                        }

                        // Store # of bones (if any)
                        if(Mesh->m_SkinInfo)
                                Mesh->m_NumBones = Mesh->m_SkinInfo->GetNumBones();

                        // Create a matching skinned mesh if bone exist
                        if(Mesh->m_SkinInfo != NULL && Mesh->m_NumBones != 0)
                        {
                                if(FAILED(Mesh->m_Mesh->CloneMeshFVF(0, Mesh->m_Mesh->GetFVF(),
                  m_Graphics->GetDevice(), &Mesh->m_SkinMesh)))
                                ReleaseCOM(Mesh->m_SkinInfo);
                        }

                        // Create an array of matrices to store bone transformations
                        if(Mesh->m_SkinInfo != NULL && Mesh->m_NumBones != 0)
                        {
                                // Create the bone matrix array and clear it out
                                Mesh->m_Matrices = new D3DXMATRIX[Mesh->m_NumBones];
                                for(i=0;i<Mesh->m_NumBones;i++)
                                {
                                        D3DXMatrixIdentity(&Mesh->m_Matrices);
                                }
                                // Create the frame mapping matrix array and clear out
                                Mesh->m_FrameMatrices = new D3DXMATRIX*[Mesh->m_NumBones];
                                for(i=0;i<Mesh->m_NumBones;i++)
                                {
                                        Mesh->m_FrameMatrices = NULL;
                                }
                        }

                // Load materials or create a default one if none
                if(!Mesh->m_NumMaterials)
                {// Create a default one
                        Mesh->m_Materials = new D3DMATERIAL9[1];
                        Mesh->m_Textures  = new LPDIRECT3DTEXTURE9[1];

                        ZeroMemory(Mesh->m_Materials, sizeof(D3DMATERIAL9));
                        Mesh->m_Materials[0].Diffuse.r = 1.0f;
                        Mesh->m_Materials[0].Diffuse.g = 1.0f;
                        Mesh->m_Materials[0].Diffuse.b = 1.0f;
                        Mesh->m_Materials[0].Diffuse.a = 1.0f;
                        Mesh->m_Materials[0].Ambient   = Mesh->m_Materials[0].Diffuse;
                        Mesh->m_Materials[0].Specular  = Mesh->m_Materials[0].Diffuse;
                        Mesh->m_Textures[0] = NULL;

                        Mesh->m_NumMaterials = 1;
                }
                else
                {// Load the materials
                        Materials = (D3DXMATERIAL*)MaterialBuffer->GetBufferPointer();
                        Mesh->m_Materials = new D3DMATERIAL9[Mesh->m_NumMaterials];
                        Mesh->m_Textures  = new LPDIRECT3DTEXTURE9[Mesh->m_NumMaterials];

                        for(i=0;i<Mesh->m_NumMaterials;i++)
                        {
                                Mesh->m_Materials = Materials.MatD3D;
                                Mesh->m_Materials.Ambient = Mesh->m_Materials.Diffuse;
                        // Build a texture path and load it
                                sprintf(Path, "%s%s", TexturePath, Materials.pTextureFilename);
                                if(FAILED(D3DXCreateTextureFromFile(m_Graphics->GetDevice(),
                                              Path,
                                              &Mesh->m_Textures)))
                                {
                                        Mesh->m_Textures = NULL;
                                }
                        }
                }
                ReleaseCOM(MaterialBuffer);
                // link in mesh
                Mesh->m_Next = m_Meshes;
                m_Meshes = Mesh;
                m_NumMeshes++;
        }
                else
                {// Find mesh in list
                        Mesh = m_Meshes->FindMesh(Name);
                }
                // Add mesh to frame
                if(Mesh != NULL)
                        ParentFrame->AddMesh(Mesh);
        }
        if(Type == TID_D3DRMAnimationSet || Type == TID_D3DRMAnimation || Type == TID_D3DRMAnimationKey)
        {
                delete [] Name;
                return;
        }
        // Release name buffer
        delete [] Name;
       
        dSize=0;
        if(SUCCEEDED(pDataObj->GetChildren(&dSize))&&pDataObj)
        {
                for(i=0;i<dSize;i++)
                {
                        pDataObj->GetChild(i,&pSubObj);

                        if(!pSubObj->IsReference())
                        {
                                ParseXFileData(pSubObj, SubFrame,TexturePath);
                                ReleaseCOM(pSubObj);
                        }
                }
        }
}

void cMesh::MapFramesToBones(sFrame *Frame)
{
        sMesh *Mesh;
        DWORD i;

        // Return if no more frames to map
        if(Frame == NULL || Frame->Name == NULL)
                return;

        // Scan through meshes looking for bone matches
        Mesh = m_Meshes;
        while(Mesh != NULL)
        {
                if(Mesh->m_SkinInfo && Mesh->m_NumBones && Mesh->m_Matrices != NULL && Mesh->m_FrameMatrices != NULL)
                {

                        for(i=0;i<Mesh->m_NumBones;i++)
                        {
                                if(!strcmp(Frame->Name, Mesh->m_SkinInfo->GetBoneName(i)))
                                {
                                        Mesh->m_FrameMatrices = &Frame->matCombined;
                                        break;
                                }
                        }
                }
                Mesh = Mesh->m_Next;
        }

        // Scan through child frames
        MapFramesToBones(Frame->Child);

        // Scan through sibling frames
        MapFramesToBones(Frame->Sibling);
}

HRESULT cMesh::Free()
{
        m_Graphics = NULL;

        m_NumMeshes = 0;
        delete m_Meshes;
        m_Meshes = NULL;

        m_NumFrames = 0;
        delete m_Frames;
        m_Frames = NULL;

        m_Min.x = m_Min.y = m_Min.z = m_Max.x = m_Max.y = m_Max.z = 0.0f;
        m_Radius = 0.0f;

        return S_OK;
}

sFrame *cMesh::GetFrame(char *Name)
{
  if(m_Frames == NULL)
    return NULL;
  return m_Frames->FindFrame(Name);
}

long cMesh::GetNumFrames()
{
  return m_NumFrames;
}

sFrame *cMesh::GetParentFrame()
{
  return m_Frames;
}

long cMesh::GetNumMeshes()
{
        return m_NumMeshes;
}

sMesh *cMesh::GetParentMesh()
{
        return m_Meshes;
}

sMesh *cMesh::GetMesh(char *Name)
{
        if(m_Meshes == NULL)
                return NULL;
        return m_Meshes->FindMesh(Name);
}

BOOL cMesh::GetBounds(float *MinX, float *MinY, float *MinZ, float *MaxX, float *MaxY, float *MaxZ, float *Radius)
{
  if(MinX != NULL)
    *MinX = m_Min.x;
  if(MinY != NULL)
    *MinY = m_Min.y;
  if(MinZ != NULL)
    *MinZ = m_Min.z;

  if(MaxX != NULL)
    *MaxX = m_Max.x;
  if(MaxY != NULL)
    *MaxY = m_Max.y;
  if(MaxZ != NULL)
    *MaxZ = m_Max.z;

  if(Radius != NULL)
    *Radius = m_Radius;

  return TRUE;
}

以前修改《DirectX 高级动画制作》 加载模型的代码,DX 9.0C化

23

主题

47

帖子

47

积分

注册会员

Rank: 2

积分
47
 楼主| 发表于 2009-2-27 17:18:00 | 显示全部楼层

Re:请教达人~~~关于骨骼动画的问题。

谢谢以上各位,搞定了,读了一下具体代码,在meshcontainer里面做了一些修改,再次感谢了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-20 06:08

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表