【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 2926|回复: 2

[转帖] 我对骨骼动画的理解

[复制链接]
发表于 2007-5-24 15:57:07 | 显示全部楼层 |阅读模式

本人研究骨骼动画时间不久,勉强写出一个可以运行的类,算是对骨骼动画入门了吧.感慨刚开始研究时资料的缺乏,我决定将我对骨骼动画的理解发表出来希望对正在研究的朋友们能有点帮助!但本人水平有限,文中难免会有不少错误,如果你对文章有异义或有什么不明白的请与我联系
QQ:517082060
邮箱:hoho4790150@126.com
要利用X文件实现骨骼动画,首先必须清楚X文件中是如何储存动画数据的.打开一个X文件,除去各种模板等东西,首先你看到的应该是一个Frame(即帧),每一帧对应了一根骨骼,而帧里面又有可能包含帧,正是通过帧的包含与被包含关系来体现骨骼的父子关系.帧里面还可能包含mesh(即网格), 为什么要把网格包含在帧里面呢?因为我们画网格的时候要把它画到世界坐标系中去,那么这个世界转换矩阵从哪来呢?显然网格绑定在哪根骨骼上就从对应的帧里面获取,所以要将网格包含在帧里面.当然帧里面还会包含一个矩阵, 这个数据是用来将骨头的位置初始化的.
接下来你就应该看到一个AnimationSet(动画集),但为了通俗起见,我称他为动作.动作里面包含了实现该动作时每根骨骼各个时刻的动画键(通俗起见,我又称它为旋转矩阵),动作里面包含的Animation就储存了一根骨骼实现该动作时各时刻的旋转矩阵,至于这个Animation对应哪根骨骼就由它里面所包含的引用决定.一般每个Animation里面都会有一个帧的引用(就是用大括号括起来的一个字符串),如{Root_Scence}.你搜索这个字符串,决对会发现前面有个同名的帧.
了解了帧与动画集的意义后就可以读取里面的数据来实现骨骼动画了.先来说说流程:
首先我们必须先读取所有的帧,并利用帧之间的包含关系来构建二叉树(构建二叉树的目的是为了清楚的表示每根骨骼的父骨骼,只要能实现这个目的,链表二叉树都一样).在构建二叉树的同时顺便把帧里面的矩阵和网格读取出来,矩阵就保存在对应的保存帧的容器里面,而网格最好提取出来保存在一个链表里面以方便后面绘制.
读取完帧的数据之后就可以读取动作数据了,每读取一个动作就把它放到一个动作的链表中去,而读取动作里面的Animation数据时也要把它们连接到一个链表里(这个链表的头结点是动作里面的一个元素),并且通过Animation里面的引用将之与帧二叉树里面对应的帧相关连(这是很重要的,我们通过Animation计算出中间的旋转矩阵后是要存储到二叉树中的,然后通过递归遍历二叉树将这些矩阵累积相乘).
存储完数据之后接下来的事情就很简单了,如果我们想显示一个名为walk的动作,就遍历动作链表找到那个动作,然后遍历动作里面的Animation链表,用线性插值法计算每根骨骼此时的旋转矩阵,并把它存储到相关连帧里面去.然后我们回到二叉树,递归遍历二叉树将计算出来的插值矩阵累积相乘得到混合矩阵.最后调用系统函数ID3DXSkinInfo::UpdateSkinnedMesh利用矩阵更新网格,接着就可以画出来了.如果你想了解UpdateSkinnedMesh函数是如何工作的,建议你去看DirectX自带例子Skinmesh里面的fx文件,如果你不懂HLSL就听我说说我的理解.我的理解是这样的:每一个网格的顶点里面除了包含坐标,纹理,材质等基础的数据之外还包含有一个骨骼的索引数组和一个对应权重值数组(权重数组里面的第几号元素就对应了骨骼数组里面第几号索引所表示的骨骼对该顶点的影响比例).遍历骨骼数组找到每一根骨骼,就可以查找到对应的帧了,从而可以提取帧里面的矩阵将其与权重值相乘得到的这个矩阵再来影响顶点坐标就实现了皮肤网格的改变.
接下来我将的的类贴到下面,大家有兴趣的可以自己看看:
SkinMesh.h
///////////////////////////////////////////////////////////////////////////////////////////
#pragma once

#include <d3dx9mesh.h>
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
#include <objbase.h>
#include <mmsystem.h>
#include <malloc.h>
#include "XFile.h"
#include <dxfile.h>


#define GXRELEASE(_p) do{if((_p)!= NULL){(_p)->Release();(_p) = NULL;}}while(0)

struct Frame
{
char *Name;
Frame* pFrameSibling;
Frame* pFrameChild;
D3DXMATRIX matRot;
D3DXMATRIX matRotOrig;
D3DXMATRIX matCombined;

Frame()
{
Name = NULL;
pFrameChild = pFrameSibling = NULL;
D3DXMatrixIdentity(&matCombined);
D3DXMatrixIdentity(&matRotOrig);
D3DXMatrixIdentity(&matRot);
}

~Frame ()
{
delete []Name;
delete pFrameSibling;
delete pFrameChild;
}
};

struct MeshContainer 
{
char *Name;
D3DMATERIAL9 *pMaterials;
DWORD NumMaterials;
LPDIRECT3DTEXTURE9 *pTextures;

ID3DXMesh *pMesh;
ID3DXMesh *pSkinMesh;
LPD3DXSKININFO pSkinInfo;
D3DXMATRIX** pBoneMatrix;
D3DXMATRIX* pBoneOffsetMat;
DWORD* pAdjacency;
MeshContainer *pMeshContainerNext;
Frame* pFrame;

MeshContainer()
{
Name = NULL;
pMaterials = NULL;
pTextures = NULL;
NumMaterials = 0;
pMesh = NULL;
pSkinInfo = NULL;
pSkinMesh = NULL;
pBoneMatrix = NULL;
pBoneOffsetMat = NULL;
pAdjacency = NULL;
pMeshContainerNext = NULL;
pFrame = NULL;
}

~MeshContainer()
{
delete []pMaterials;
if (pTextures)
{
for(DWORD i = 0; i < NumMaterials; i++)
{
GXRELEASE(pTextures);
}
delete []pTextures;
}
GXRELEASE(pMesh);
GXRELEASE(pSkinInfo);
GXRELEASE(pSkinMesh);
delete []pBoneMatrix;
delete []Name;
delete []pAdjacency;
delete []pMeshContainerNext;
delete pFrame;
}
};

struct RotateKeyXFile
{
DWORD dwTime;
DWORD dwFloats;
float w;
float x;
float y;
float z;
};

struct D3DKeyXFile
{
DWORD dwTime;
DWORD dwFloats;
D3DXVECTOR3 vVec;
};

struct MatrixKeyXFile
{
DWORD dwTime;
DWORD dwFloats;
D3DXMATRIX mat;
};

struct RotateKey
{
DWORD dwTime;
D3DXQUATERNION quatRotate;
};

struct PositionKey
{
DWORD dwTime;
D3DXVECTOR3 vPos;
};

struct ScaleKey
{
DWORD dwTime;
D3DXVECTOR3 vScale;
};

struct MatrixKey
{
DWORD dwTime;
D3DXMATRIX mat;
};

struct Animation
{
char *Name;
Frame *pFrame;
Animation *pAnimationNext;

PositionKey *pPositionKeys;
UINT nPositionKeys;
RotateKey *pRotateKeys;
UINT nRotateKeys;
ScaleKey *pScaleKeys;
UINT nScaleKeys;
MatrixKey *pMatrixKeys;
UINT nMatrixKeys;
Animation()
{
Name = NULL;
pFrame = NULL;
pAnimationNext = NULL;
pPositionKeys = NULL;
nPositionKeys = 0;
pRotateKeys = NULL;
nRotateKeys = 0;
pScaleKeys = NULL;
nScaleKeys = 0;
pMatrixKeys = NULL;
nMatrixKeys = 0;
}
~Animation()
{
delete []Name;
delete pFrame;
delete pAnimationNext;
delete []pPositionKeys;
delete []pRotateKeys;
delete []pScaleKeys;
delete []pMatrixKeys;
}
};

struct AnimationSet
{
char *Name;
DWORD NumAnimation;
Animation *pAnimation;
AnimationSet *pAnimationSetNext;
DWORD CurTime;
};


class SkinMesh
{
public:
SkinMesh(LPDIRECT3DDEVICE9 g_pd3dDevice);
~SkinMesh(void);
Frame* FindFrame(Frame* frame, char* Name);
void AddFrame(Frame* parentFrame, Frame* pFrame);
void AddMesh(Frame* frame, MeshContainer* pMeshContainer);
HRESULT FindBones(void);
HRESULT FrameMove(void);
HRESULT DrawFrames(void);
void SetTime(Animation* pAnim, float fGlobalTime);
HRESULT DrawMeshContainer(MeshContainer* pmcMesh);
HRESULT Render();
HRESULT LoadFromXFile(TCHAR* pFileName);
HRESULT LoadMesh(LPD3DXFILEDATA pFileData, Frame* pFrameParent);
HRESULT UpdateFrames(Frame* pFrame, D3DXMATRIX& mat);
HRESULT SetAnimationName(char* AnimateName);
HRESULT LoadFrame(LPD3DXFILEDATA pFileData, Frame* pFrameParent);
HRESULT LoadAnimationSet(LPD3DXFILEDATA pFileData);
HRESULT LoadAnimation(LPD3DXFILEDATA pFileData);
LPDIRECT3DDEVICE9 pd3dDevice;
AnimationSet* pAnimSetHead;
Frame* pFrameRoot;
MeshContainer* pMeshHead;
DWORD Options;
DWORD CurTime;
AnimationSet* pAnimSetCur;
};

 楼主| 发表于 2007-5-24 15:58:19 | 显示全部楼层

SkinMesh.cpp
///////////////////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include ".\skinmesh.h"

SkinMesh::SkinMesh(LPDIRECT3DDEVICE9 g_pd3dDevice)
: pAnimSetHead(NULL)
, pFrameRoot(NULL)
, pMeshHead(NULL)
, Options(0)
, CurTime(0)
, pAnimSetCur(NULL)
{
pd3dDevice  = g_pd3dDevice;
Options  = 0;
pFrameRoot  = new Frame();
pAnimSetHead = NULL;
pMeshHead  = NULL;
CurTime  = 0;
pAnimSetCur  = pAnimSetHead;
}

SkinMesh::~SkinMesh(void)
{
}

Frame* SkinMesh::FindFrame(Frame* frame, char* Name)
{
Frame *pFrame;
if((frame->Name != NULL)&&strcmp(frame->Name, Name) == 0)
return frame;
if(frame->pFrameChild != NULL)
{
pFrame = FindFrame(frame->pFrameChild, Name);
if(pFrame != NULL)
return pFrame;
}
if(frame->pFrameSibling != NULL)
{
pFrame = FindFrame(frame->pFrameSibling, Name);
if(pFrame != NULL)
return pFrame;
}
return NULL;
}

void SkinMesh::AddFrame(Frame* parentFrame, Frame* pFrame)
{
if (parentFrame->pFrameChild == NULL)
{
parentFrame->pFrameChild = pFrame;
}else
{
Frame* frame = parentFrame->pFrameChild;
while (frame->pFrameSibling != NULL)
{
frame = frame->pFrameSibling;
}
frame->pFrameSibling = pFrame;
}
}

void SkinMesh::AddMesh(Frame* frame, MeshContainer* pMeshContainer)
{
pMeshContainer->pMeshContainerNext = pMeshHead;
pMeshHead = pMeshContainer;
pMeshContainer = NULL;
if(frame)
{
pMeshHead->pFrame = frame;
}
}

HRESULT SkinMesh::FindBones(void)
{
MeshContainer *pMeshContainer;
pMeshContainer = pMeshHead;
while(NULL != pMeshContainer)
{
if(pMeshContainer->pSkinInfo)
{
for( DWORD i = 0; i<pMeshContainer->pSkinInfo->GetNumBones(); i++)
{
Frame *frame = FindFrame(pFrameRoot, (char*)pMeshContainer->pSkinInfo->GetBoneName(i));
pMeshContainer->pBoneMatrix = &(frame->matCombined);
}
}
pMeshContainer = pMeshContainer->pMeshContainerNext;
}
return E_NOTIMPL;
}

HRESULT SkinMesh::FrameMove(void)
{
CurTime = CurTime+100;
if(CurTime>1.0e15f)
CurTime = 0;
Animation *pAnimCur = pAnimSetCur->pAnimation;
while (pAnimCur != NULL)
{
SetTime(pAnimCur, CurTime);
pAnimCur = pAnimCur->pAnimationNext;
}
return E_NOTIMPL;
}

HRESULT SkinMesh:rawFrames(void)
{
MeshContainer *pmc = pMeshHead;

while (pmc != NULL)
{
pd3dDevice->SetTransform(D3DTS_WORLD, &pmc->pFrame->matCombined);

DrawMeshContainer(pmc);

pmc = pmc->pMeshContainerNext;
}

return E_NOTIMPL;
}

void SkinMesh::SetTime(Animation* pAnim, float fGlobalTime)
{
UINT iKey;
UINT dwp2;
UINT dwp3; D3DXMATRIX matResult;
D3DXMATRIX matTemp; float fTime1;
float fTime2;
float fLerpvalue; D3DXVECTOR3 vScale;
D3DXVECTOR3 vPos;
D3DXQUATERNION quat; float fTime; if (pAnim->pMatrixKeys )
{
fTime = (float)fmod(fGlobalTime, pAnim->pMatrixKeys[pAnim->nMatrixKeys-1].dwTime);
for (iKey = 0 ;iKey < pAnim->nMatrixKeys ; iKey++)
{
if ((float)pAnim->pMatrixKeys[iKey].dwTime > fTime)
{
dwp3 = iKey;
if (iKey > 0)
dwp2= iKey - 1;
else
dwp2 = iKey;
break;
}
} fTime1 = (float)pAnim->pMatrixKeys[dwp2].dwTime;
fTime2 = (float)pAnim->pMatrixKeys[dwp3].dwTime; if ((fTime2 - fTime1) ==0)
fLerpvalue = 0;
else
fLerpvalue =  (fTime - fTime1) / (fTime2 - fTime1);

if (fLerpvalue > 0.5)
iKey = dwp3;
else
iKey = dwp2;
pAnim->pFrame->matRot = pAnim->pMatrixKeys[iKey].mat;
}
else
{
D3DXMatrixIdentity(&matResult);
if (pAnim->pScaleKeys)
{
dwp2 = dwp3 = 0;
fTime = (float)fmod(fGlobalTime, pAnim->pScaleKeys[pAnim->nScaleKeys-1].dwTime); for (iKey = 0 ;iKey < pAnim->nScaleKeys ; iKey++)
{
if ((float)pAnim->pScaleKeys[iKey].dwTime > fTime)
{
dwp3 = iKey; if (iKey > 0)
dwp2= iKey - 1;
else
dwp2 = iKey;
break;
}
}
fTime1 = (float)pAnim->pScaleKeys[dwp2].dwTime;
fTime2 = (float)pAnim->pScaleKeys[dwp3].dwTime;
if ((fTime2 - fTime1) ==0)
fLerpvalue = 0;
else
fLerpvalue =  (fTime - fTime1) / (fTime2 - fTime1);
D3DXVec3Lerp(&vScale,
&pAnim->pScaleKeys[dwp2].vScale,
&pAnim->pScaleKeys[dwp3].vScale,
fLerpvalue);
D3DXMatrixScaling(&matTemp, vScale.x, vScale.y, vScale.z);
D3DXMatrixMultiply(&matResult, &matResult, &matTemp);
pAnim->pFrame->matRot = matResult;
}
else if (pAnim->pRotateKeys )
{
dwp2 = dwp3 = 0;
fTime = (float)fmod(fGlobalTime, pAnim->pRotateKeys[pAnim->nRotateKeys-1].dwTime); for (iKey = 0 ;iKey < pAnim->nRotateKeys ; iKey++)
{
if ((float)pAnim->pRotateKeys[iKey].dwTime > fTime)
{
dwp3 = iKey;
if (iKey > 0)
dwp2= iKey - 1;
else
dwp2 = iKey;
break;
}
} fTime1 = (float)pAnim->pRotateKeys[dwp2].dwTime;
fTime2 = (float)pAnim->pRotateKeys[dwp3].dwTime;
if ((fTime2 - fTime1) ==0)
fLerpvalue = 0;
else
fLerpvalue =  (fTime - fTime1) / (fTime2 - fTime1); D3DXQUATERNION q1,q2;
q1.x =-pAnim->pRotateKeys[dwp2].quatRotate.x;
q1.y =-pAnim->pRotateKeys[dwp2].quatRotate.y;
q1.z =-pAnim->pRotateKeys[dwp2].quatRotate.z;
q1.w =pAnim->pRotateKeys[dwp2].quatRotate.w;

q2.x =-pAnim->pRotateKeys[dwp3].quatRotate.x;
q2.y =-pAnim->pRotateKeys[dwp3].quatRotate.y;
q2.z =-pAnim->pRotateKeys[dwp3].quatRotate.z;
q2.w =pAnim->pRotateKeys[dwp3].quatRotate.w;
D3DXQuaternionSlerp(&quat,
&q1,
&q2,
fLerpvalue);
D3DXMatrixRotationQuaternion(&matTemp, &quat);
D3DXMatrixMultiply(&matResult, &matResult, &matTemp);
pAnim->pFrame->matRot = matResult;
}
else if (pAnim->pPositionKeys)
{
dwp2=dwp3=0;
fTime = (float)fmod(fGlobalTime, pAnim->pPositionKeys[pAnim->nRotateKeys-1].dwTime);
for (iKey = 0 ;iKey < pAnim->nPositionKeys ; iKey++)
{
if ((float)pAnim->pPositionKeys[iKey].dwTime > fTime)
{
dwp3 = iKey;
if (iKey > 0)
dwp2= iKey - 1;
else
dwp2 = iKey; break;
}
}
fTime1 = (float)pAnim->pPositionKeys[dwp2].dwTime;
fTime2 = (float)pAnim->pPositionKeys[dwp3].dwTime;
if ((fTime2 - fTime1) ==0)
fLerpvalue = 0;
else fLerpvalue =  (fTime - fTime1) / (fTime2 - fTime1);
D3DXVec3Lerp((D3DXVECTOR3*)&vPos,
&pAnim->pPositionKeys[dwp2].vPos, &pAnim->pPositionKeys[dwp3].vPos,
fLerpvalue);
D3DXMatrixTranslation(&matTemp, vPos.x, vPos.y, vPos.z);
D3DXMatrixMultiply(&matResult, &matResult, &matTemp);
pAnim->pFrame->matRot = matResult;
} }
}

HRESULT SkinMesh:rawMeshContainer(MeshContainer* pmcMesh)
{
UINT ipattr; PBYTE pbVerticesSrc;
PBYTE pbVerticesDest;
if( pmcMesh->pSkinInfo && pmcMesh->pSkinInfo->GetNumBones())
{
D3DCAPS9 caps;
pd3dDevice->GetDeviceCaps(&caps);
DWORD cBones = pmcMesh->pSkinInfo->GetNumBones();
D3DXMATRIX* BoneMatrices = NULL;
BoneMatrices = new D3DXMATRIX[cBones];
for(DWORD iBone = 0; iBone<cBones; iBone++)
D3DXMatrixMultiply(&BoneMatrices[iBone], &pmcMesh->pBoneOffsetMat[iBone], pmcMesh->pBoneMatrix[iBone]);
D3DXMATRIX Indentity;
D3DXMatrixIdentity(&Indentity);
pd3dDevice->SetTransform(D3DTS_WORLD, &Indentity);
pmcMesh->pMesh->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&pbVerticesDest);
pmcMesh->pSkinMesh->LockVertexBuffer(0, (LPVOID*)&pbVerticesSrc);

pmcMesh->pSkinInfo->UpdateSkinnedMesh(BoneMatrices, NULL, pbVerticesSrc, pbVerticesDest);

pmcMesh->pSkinMesh->UnlockVertexBuffer(); pmcMesh->pMesh->UnlockVertexBuffer();

for(ipattr = 0; ipattr<pmcMesh->NumMaterials; ipattr++)
{
pd3dDevice->SetMaterial(&(pmcMesh->pMaterials[ipattr]));
pd3dDevice->SetTexture(0, pmcMesh->pTextures[ipattr]);
pmcMesh->pMesh->DrawSubset(ipattr);
}
}else
{
for(ipattr = 0; ipattr<pmcMesh->NumMaterials; ipattr++)
{
pd3dDevice->SetMaterial(&(pmcMesh->pMaterials[ipattr]));
pd3dDevice->SetTexture(0, pmcMesh->pTextures[ipattr]);
pmcMesh->pMesh->DrawSubset(ipattr);
}
}
return E_NOTIMPL;
}

HRESULT SkinMesh::Render()
{
D3DXMatrixIdentity(&pFrameRoot->matRot) ; D3DXMATRIX mat; D3DXMatrixIdentity(&mat); FrameMove(); UpdateFrames(pFrameRoot, mat); DrawFrames();
return E_NOTIMPL;
}

HRESULT SkinMesh:oadFromXFile(TCHAR* pFileName)
{
HRESULT hr = S_OK;
LPD3DXFILE pFile = NULL;
LPD3DXFILEENUMOBJECT pFileEnumObject = NULL;
LPD3DXFILEDATA pFileData = NULL;
GUID type;
hr = D3DXFileCreate(&pFile);
if (FAILED(hr))
return hr;
hr = pFile->RegisterTemplates((LPVOID)D3DRM_XTEMPLATES ,D3DRM_XTEMPLATE_BYTES);
if(FAILED(hr))
return hr;
hr = pFile->CreateEnumObject((LPVOID)pFileName, DXFILELOAD_FROMFILE , &pFileEnumObject);
if(FAILED(hr))
return hr;
DWORD Size;
pFileEnumObject->GetChildren(&Size);
for(DWORD i = 0 ; i < Size ; i++)
{
pFileEnumObject->GetChild(i, &pFileData);
pFileData->GetType(&type);
if (type == TID_D3DRMFrame)
{
LoadFrame(pFileData, pFrameRoot);
}
if (type == TID_D3DRMAnimationSet)
{
LoadAnimationSet(pFileData);
}

GXRELEASE(pFileData);
} FindBones(); pFrameRoot->matRotOrig = pFrameRoot->matRot;

GXRELEASE(pFileEnumObject);
GXRELEASE(pFile);
return E_NOTIMPL;
}

HRESULT SkinMesh:oadMesh(LPD3DXFILEDATA pFileData, Frame* pFrameParent)
{
HRESULT hr = S_OK;
MeshContainer *pmcMesh = NULL;
LPD3DXBUFFER pMaterialsbuf = NULL;
LPD3DXBUFFER pAdjacencybuf = NULL;
DWORD NumName;
UINT cFaces;
UINT iMaterial;
pmcMesh = new MeshContainer(); pFileData->GetName(NULL, &NumName);
if(NumName>0)
{
pmcMesh->Name = new char[NumName];
pFileData->GetName(pmcMesh->Name, &NumName);
}else
pmcMesh->Name = "NoNameMesh";
D3DXLoadSkinMeshFromXof(pFileData, Options, pd3dDevice, &pAdjacencybuf, &pMaterialsbuf, NULL,
&pmcMesh->NumMaterials,  &pmcMesh->pSkinInfo, &pmcMesh->pSkinMesh); pmcMesh->pSkinMesh->CloneMeshFVF(Options, pmcMesh->pSkinMesh->GetFVF(),pd3dDevice, &pmcMesh->pMesh);
DWORD NumBones = pmcMesh->pSkinInfo->GetNumBones();
if(NumBones>0)
{
pmcMesh->pBoneMatrix = new D3DXMATRIX*[NumBones];

pmcMesh->pBoneOffsetMat = new D3DXMATRIX[NumBones];
for(DWORD i = 0; i < NumBones; i++)
pmcMesh->pBoneOffsetMat = (*pmcMesh->pSkinInfo->GetBoneOffsetMatrix(i));

LPDWORD pAdjacency = static_cast<LPDWORD>(pAdjacencybuf->GetBufferPointer());
cFaces = pmcMesh->pSkinMesh->GetNumFaces();
pmcMesh->pAdjacency = new DWORD[cFaces*3];
memcpy(pmcMesh->pAdjacency, pAdjacency, cFaces*3*sizeof(DWORD));
}else
{
pmcMesh->pSkinInfo = NULL;
}

 楼主| 发表于 2007-5-24 15:58:29 | 显示全部楼层


if(pmcMesh->NumMaterials>0)
{
pmcMesh->pMaterials = new D3DMATERIAL9[pmcMesh->NumMaterials];
pmcMesh->pTextures = new  LPDIRECT3DTEXTURE9[pmcMesh->NumMaterials];
LPD3DXMATERIAL pMaterials = (LPD3DXMATERIAL)pMaterialsbuf->GetBufferPointer();
for (iMaterial = 0; iMaterial<pmcMesh->NumMaterials; iMaterial++)
{
pmcMesh->pMaterials[iMaterial] = pMaterials[iMaterial].MatD3D;
pmcMesh->pTextures[iMaterial] = NULL;
if(pMaterials[iMaterial].pTextureFilename != NULL)
D3DXCreateTextureFromFile(pd3dDevice, pMaterials[iMaterial].pTextureFilename, &(pmcMesh->pTextures[iMaterial]));
}
}else
{
pmcMesh->pMaterials = new D3DMATERIAL9[1];
pmcMesh->pTextures = new LPDIRECT3DTEXTURE9[1];
memset(pmcMesh->pMaterials, 0, sizeof(D3DXMATERIAL));
pmcMesh->pMaterials[0].Diffuse.r = 0.5f;
pmcMesh->pMaterials[0].Diffuse.g = 0.5f;
pmcMesh->pMaterials[0].Diffuse.b = 0.5f;
pmcMesh->pMaterials[0].Specular  = pmcMesh->pMaterials[0].Diffuse;
pmcMesh->pTextures[0] = NULL;
} AddMesh(pFrameParent, pmcMesh); pmcMesh = NULL; delete pmcMesh;
GXRELEASE(pAdjacencybuf);
GXRELEASE(pMaterialsbuf);
return E_NOTIMPL;
}

HRESULT SkinMesh::UpdateFrames(Frame* pFrame, D3DXMATRIX& mat)
{
D3DXMatrixMultiply(&pFrame->matCombined, &pFrame->matRot, &mat);
Frame *pframeChild = pFrame->pFrameChild; while(pframeChild != NULL)
{
UpdateFrames(pframeChild, pFrame->matCombined);
pframeChild = pframeChild->pFrameSibling;
}
return E_NOTIMPL;
}

HRESULT SkinMesh::SetAnimationName(char* AnimateName)
{
pAnimSetCur = pAnimSetHead;

while(pAnimSetCur && strcmp(pAnimSetCur->Name, AnimateName))
{
pAnimSetCur = pAnimSetCur->pAnimationSetNext;
}
return E_NOTIMPL;
}

HRESULT SkinMesh:oadFrame(LPD3DXFILEDATA pFileData, Frame* pFrameParent)
{
LPD3DXFILEDATA pFileDataChild = NULL; DWORD NumName = 0; GUID type;
pFileData->GetType(&type);
if(type == TID_D3DRMMesh)
{
LoadMesh(pFileData, pFrameParent);
}
else if (type == TID_D3DRMFrameTransformMatrix)
{
if(pFrameParent != NULL)
{
D3DXMATRIX *pMat;
DWORD Size;
//pFileData->GetData(NULL, &Size, (PVOID*)&pMat);
pFileData->Lock(&Size, (LPCVOID*)&pMat);
pFrameParent->matRot = *pMat;
pFrameParent->matRotOrig = *pMat;
pFileData->Unlock();
}
}else if (type == TID_D3DRMFrame)
{
Frame* pFrame = new Frame();
pFileData->GetName(NULL, &NumName); if(NumName > 0)
{
pFrame->Name = new char[NumName];
pFileData->GetName(pFrame->Name, &NumName);
}else
pFrame->Name = "NoName";

AddFrame(pFrameParent, pFrame);

DWORD Size;
pFileData->GetChildren(&Size);
for (DWORD i = 0 ; i < Size ; i++)
{
pFileData->GetChild(i, &pFileDataChild);
LoadFrame(pFileDataChild, pFrame);
GXRELEASE(pFileDataChild);
}

}
return E_NOTIMPL;
}

HRESULT SkinMesh:oadAnimationSet(LPD3DXFILEDATA pFileData)
{
LPD3DXFILEDATA pFileDataChild = NULL; GUID type;
DWORD NumName;

AnimationSet*  pAnimSetCur = new AnimationSet();
pFileData->GetName(NULL, &NumName); if(NumName>0)
{
pAnimSetCur->Name = new char[NumName];
pFileData->GetName(pAnimSetCur->Name, &NumName);
} else pAnimSetCur->Name = "NoName";
pAnimSetCur->pAnimationSetNext = pAnimSetHead;
pAnimSetHead = pAnimSetCur;

DWORD Size;
pFileData->GetChildren(&Size);
for (DWORD i = 0 ; i < Size ; i++)
{
pFileData->GetChild(i , &pFileDataChild);
pFileDataChild->GetType(&type);
if (type == TID_D3DRMAnimation)
{
LoadAnimation(pFileDataChild);
}
}
return E_NOTIMPL;
}

HRESULT SkinMesh:oadAnimation(LPD3DXFILEDATA pFileData)
{
GUID type;
RotateKeyXFile *pFileRotateKey;
D3DKeyXFile *pFileScaleKey;
D3DKeyXFile *pFilePosKey;
MatrixKeyXFile *pFileMatrixKey;
DWORD NumName;
PBYTE pData;
DWORD dwKeyType;
DWORD cKeys;
DWORD iKey;
Animation* pAnimCur = new Animation();
pFileData->GetName(NULL, &NumName);
if (NumName>0)
{
pAnimCur->Name = new char[NumName];
pFileData->GetName(pAnimCur->Name, &NumName);
}else
pAnimCur->Name = "NoName";

pAnimCur->pAnimationNext = pAnimSetHead->pAnimation;
pAnimSetHead->pAnimation = pAnimCur;

LPD3DXFILEDATA pFileDataChild = NULL;

DWORD Size;
pFileData->GetChildren(&Size);
for (DWORD i = 0 ; i < Size ; i++)
{
pFileData->GetChild(i , &pFileDataChild);
if(pFileDataChild->IsReference())
{
pFileDataChild->GetType(&type);
if (type == TID_D3DRMFrame)
{
DWORD Size;
pFileDataChild->GetName(NULL, &Size);
char* Name = (char*)_alloca(Size);
pFileDataChild->GetName(Name, &Size);
pAnimCur->pFrame = FindFrame(pFrameRoot, Name);
}
}

if(!pFileDataChild->IsReference())
{
pFileDataChild->GetType(&type);
if (TID_D3DRMAnimationKey == type)
{
Animation *pAnimCur = pAnimSetHead->pAnimation;
DWORD Size;
pFileDataChild->Lock(&Size, (LPCVOID*)&pData);
dwKeyType = ((DWORD*)pData)[0];
cKeys = ((DWORD*)pData)[1];
if(dwKeyType == 0)
{
pAnimCur->pRotateKeys = new RotateKey[cKeys]; pAnimCur->nRotateKeys = cKeys; pFileRotateKey = (RotateKeyXFile*)(pData+(sizeof(DWORD)*2)); for(iKey = 0; iKey < cKeys; iKey++)
{
pAnimCur->pRotateKeys[iKey].dwTime = pFileRotateKey->dwTime; pAnimCur->pRotateKeys[iKey].quatRotate.x = pFileRotateKey->x; pAnimCur->pRotateKeys[iKey].quatRotate.y = pFileRotateKey->y; pAnimCur->pRotateKeys[iKey].quatRotate.z = pFileRotateKey->z; pAnimCur->pRotateKeys[iKey].quatRotate.w = pFileRotateKey->w;
pFileRotateKey += 1;
} }
else if (dwKeyType == 1)
{
pAnimCur->pScaleKeys = new ScaleKey[cKeys]; pAnimCur->nScaleKeys = cKeys;
pFileScaleKey = (D3DKeyXFile*)(pData + (sizeof(DWORD)*2)); for(iKey = 0; iKey<cKeys; iKey++)
{
pAnimCur->pScaleKeys[iKey].dwTime = pFileScaleKey->dwTime;
pAnimCur->pScaleKeys[iKey].vScale = pFileScaleKey->vVec;
pFileScaleKey += 1;
}
}
else if (dwKeyType == 2)
{
pAnimCur->pPositionKeys = new PositionKey[cKeys];
pAnimCur->nPositionKeys = cKeys;
pFilePosKey = (D3DKeyXFile*)(pData + (sizeof(DWORD)*2));
for (iKey = 0; iKey <cKeys; iKey++)
{
pAnimCur->pPositionKeys[iKey].dwTime = pFilePosKey->dwTime;
pAnimCur->pPositionKeys[iKey].vPos   = pFilePosKey->vVec;
pFilePosKey += 1;
}
}
else if(dwKeyType == 4)
{
pAnimCur->pMatrixKeys = new MatrixKey[cKeys];
pAnimCur->nMatrixKeys = cKeys;
pFileMatrixKey = (MatrixKeyXFile*)(pData + (sizeof(DWORD)*2));
for(iKey = 0; iKey < cKeys; iKey++)
{
pAnimCur->pMatrixKeys[iKey].dwTime = pFileMatrixKey->dwTime;
pAnimCur->pMatrixKeys[iKey].mat = pFileMatrixKey->mat;
pFileMatrixKey += 1;
}
}
}
}
GXRELEASE(pFileDataChild);
}

GXRELEASE(pFileData);
return E_NOTIMPL;
}

由于本人写代码时没有养成写注释的好习惯,所以如果你对这个类实在看不懂请尽管与我联系,我一定抽时间为你解答!
添加一句,头文件中添加的"XFile.h"是从DirectX高级动画制作中拿来用的.因为作者说直接导入rmxfguid.h和rmxftmpl.h容易出问题,所以稍微处理了一下.我现在把这两个文件也贴出来
XFile.h
////////////////////////////////////////////////////////////////////////////
#include "rmxfguid.h"
extern unsigned char D3DRM_XTEMPLATES[];
#define D3DRM_XTEMPLATE_BYTES 3278

XFile.cpp
////////////////////////////////////////////////////////////////////////////
#include "rmxftmpl.h"

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-5-6 12:24

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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