您的位置:首页 > 其它

(转)如何使用3dmax导出插件导出模型信息

2012-11-22 09:45 197 查看
最近研究了下3dmax导出插件的东西.游戏编程精粹2上给过部分代码,但不完整而且我觉得那上面的实现并不好.这里贴下我的实现.

首先定义骨骼的结构:

view plaincopy to clipboardprint?

struct Bone

{

INode* pNode;//该骨骼的节点

int parent;//父节点序号

typedef std::vector<int> Child_Vec;

Child_Vec childs;//子节点序号

Matrix3 matrix;//基本变换矩阵

};

typedef std::vector<Bone> Bone_Vec;

Bone_Vec m_bones;

struct Bone

{

INode* pNode;//该骨骼的节点

int parent;//父节点序号

typedef std::vector<int> Child_Vec;

Child_Vec childs;//子节点序号

Matrix3 matrix;//基本变换矩阵

};

typedef std::vector<Bone> Bone_Vec;

Bone_Vec m_bones;

我将骨骼结构放入一个顺序表中,Bone::parent和Bone::childs中存放的都是这个顺序表中的索引号.

然后是权重信息.精粹2上是将权重信息放到骨骼的结构中去,我认为这样不太好.因为如果要使用硬件shader实现骨骼动画的话,是需要把权重信息放到顶点缓冲中去传送给显卡的,因此应该放到每个顶点的信息中去.

我是这样定义:

  typedef std::map<int, float> Weight_Vertx;//权重顶点

其中键是骨骼的索引号,值是权重.

typedef std::vector<Weight_Vertx> Weight_Vertx_List;//权重顶点列表

Weight_Vertx_List m_weight_vertexs;//权重顶点

最终希望的是读取骨架结构,放入m_bones中,然后读取每点的权重,放入m_weight_vertexs

中.

=============================传说中的分割线======================================

下面先给出整个导出类的定义:

view plaincopy to clipboardprint?

class Export_Mesh

{

public:

Export_Mesh(INode* pRoot);

~Export_Mesh();

bool export_file(const TCHAR* name);

private:

void export_mesh(INode* pNode);

int load_bone_struct(INode* pNode, int parentIdx);//读取骨架结构

bool load_bone_weights(INode* pNode);

bool is_mesh(INode* pNode);//判断一个节点是否是模型

bool is_bone(INode* pNode);//判断一个节点是否是骨骼

int get_bone_index(INode* pNode);//取得一个骨骼节点的序号

Modifier* get_mod(INode* pNode, Class_ID id);//取得指定变形器

void get_skin_weights(INode* pNode, Modifier* pMod);//取得皮肤权重

void get_physique_weights(INode* pNode, Modifier* pMod);//取得体形权重

private:

INode* m_root;

typedef std::map<int, float> Weight_Vertx;//权重顶点

typedef std::vector<Weight_Vertx> Weight_Vertx_List;//权重顶点列表

Weight_Vertx_List m_weight_vertexs;//权重顶点

//一块骨骼

struct Bone

{

INode* pNode;//该骨骼的节点

int parent;//父节点序号

typedef std::vector<int> Child_Vec;

Child_Vec childs;//子节点序号

Matrix3 matrix;//基本变换矩阵

};

typedef std::vector<Bone> Bone_Vec;

Bone_Vec m_bones;

};

class Export_Mesh

{

public:

Export_Mesh(INode* pRoot);

~Export_Mesh();

bool export_file(const TCHAR* name);

private:

void export_mesh(INode* pNode);

int load_bone_struct(INode* pNode, int parentIdx);//读取骨架结构

bool load_bone_weights(INode* pNode);

bool is_mesh(INode* pNode);//判断一个节点是否是模型

bool is_bone(INode* pNode);//判断一个节点是否是骨骼

int get_bone_index(INode* pNode);//取得一个骨骼节点的序号

Modifier* get_mod(INode* pNode, Class_ID id);//取得指定变形器

void get_skin_weights(INode* pNode, Modifier* pMod);//取得皮肤权重

void get_physique_weights(INode* pNode, Modifier* pMod);//取得体形权重

private:

INode* m_root;

typedef std::map<int, float> Weight_Vertx;//权重顶点

typedef std::vector<Weight_Vertx> Weight_Vertx_List;//权重顶点列表

Weight_Vertx_List m_weight_vertexs;//权重顶点

//一块骨骼

struct Bone

{

INode* pNode;//该骨骼的节点

int parent;//父节点序号

typedef std::vector<int> Child_Vec;

Child_Vec childs;//子节点序号

Matrix3 matrix;//基本变换矩阵

};

typedef std::vector<Bone> Bone_Vec;

Bone_Vec m_bones;

};

先给出几个基本的函数的实现,在精粹2上都有的:

view plaincopy to clipboardprint?

bool Export_Mesh::is_mesh(INode* pNode)

{

if(NULL == pNode) return false;

ObjectState os = pNode->EvalWorldState(0);

if(!os.obj) return false;

return os.obj->SuperClassID() == GEOMOBJECT_CLASS_ID;

}

//-----------------------------------------------------------------------------

bool Export_Mesh::is_bone(INode* pNode)

{

if(NULL == pNode) return false;

ObjectState os = pNode->EvalWorldState(0);

if(!os.obj) return false;

if( os.obj->ClassID() == Class_ID(BONE_CLASS_ID, 0) ) return true;

if( os.obj->ClassID() == Class_ID(DUMMY_CLASS_ID, 0) ) return false;

Control* cont = pNode->GetTMController();

//Biped部分

return cont->ClassID() == BIPSLAVE_CONTROL_CLASS_ID || //Biped root "Bip01"

cont->ClassID() == BIPBODY_CONTROL_CLASS_ID;

}

bool Export_Mesh::is_mesh(INode* pNode)

{

if(NULL == pNode) return false;

ObjectState os = pNode->EvalWorldState(0);

if(!os.obj) return false;

return os.obj->SuperClassID() == GEOMOBJECT_CLASS_ID;

}

//-----------------------------------------------------------------------------

bool Export_Mesh::is_bone(INode* pNode)

{

if(NULL == pNode) return false;

ObjectState os = pNode->EvalWorldState(0);

if(!os.obj) return false;

if( os.obj->ClassID() == Class_ID(BONE_CLASS_ID, 0) ) return true;

if( os.obj->ClassID() == Class_ID(DUMMY_CLASS_ID, 0) ) return false;

Control* cont = pNode->GetTMController();

//Biped部分

return cont->ClassID() == BIPSLAVE_CONTROL_CLASS_ID || //Biped root "Bip01"

cont->ClassID() == BIPBODY_CONTROL_CLASS_ID;

}

我改动的一点是取得骨骼的索引值(get_bone_index函数).按照精粹2的写法,取得的索引值不是从0开始连续的,因此不容易按照他给的索引值放到一个顺序表中.因此我换了一种方法.

还记得在struct Bone结构中的INode* pNode;指针么,我是先读取整个骨架结构,然后将每个读取到的骨骼放入顺序表中,并记录下每个骨骼的节点指针.这样需要取得指定骨骼节点的索引只需要去查骨骼列表就好了.废话不多说了,实现如下:

view plaincopy to clipboardprint?

int Export_Mesh::load_bone_struct(INode* pNode, int parentIdx)

{

//如果该节点为骨骼节点

if(this->is_bone(pNode))

{

//向骨骼列表中添加该节点

Bone bone;

bone.pNode = pNode;//记录该节点指针

bone.parent = parentIdx;//记录父节点索引

bone.matrix = pNode->GetNodeTM(0.0f);//记录基本变换矩阵

bone.matrix.NoScale();

bone.matrix.Invert();

m_bones.push_back(bone);

const int currIdx = static_cast<int>(m_bones.size() - 1);

//递归遍历所有子节点

for(int i=0;i<pNode->NumberOfChildren();i++)

{

INode* cNode = pNode->GetChildNode(i);

int cIdx = this->load_bone_struct(pNode->GetChildNode(i), currIdx);

if(cIdx >= 0)

{

m_bones.at(currIdx).childs.push_back(cIdx);

}

}

return currIdx;

}

else//如果该节点不是骨骼节点,则递归遍历子节点

{

for(int i = 0; i < pNode->NumberOfChildren(); ++i)

{

this->load_bone_struct(pNode->GetChildNode(i), -1);

}

return -1;

}

}

int Export_Mesh::load_bone_struct(INode* pNode, int parentIdx)

{

//如果该节点为骨骼节点

if(this->is_bone(pNode))

{

//向骨骼列表中添加该节点

Bone bone;

bone.pNode = pNode;//记录该节点指针

bone.parent = parentIdx;//记录父节点索引

bone.matrix = pNode->GetNodeTM(0.0f);//记录基本变换矩阵

bone.matrix.NoScale();

bone.matrix.Invert();

m_bones.push_back(bone);

const int currIdx = static_cast<int>(m_bones.size() - 1);

//递归遍历所有子节点

for(int i=0;i<pNode->NumberOfChildren();i++)

{

INode* cNode = pNode->GetChildNode(i);

int cIdx = this->load_bone_struct(pNode->GetChildNode(i), currIdx);

if(cIdx >= 0)

{

m_bones.at(currIdx).childs.push_back(cIdx);

}

}

return currIdx;

}

else//如果该节点不是骨骼节点,则递归遍历子节点

{

for(int i = 0; i < pNode->NumberOfChildren(); ++i)

{

this->load_bone_struct(pNode->GetChildNode(i), -1);

}

return -1;

}

}

在这个函数完成工作后,就可以通过get_bone_index函数查找骨骼的索引了.

view plaincopy to clipboardprint?

int Export_Mesh::get_bone_index(INode* pNode)

{

//测试该节点是否为骨骼节点

if(!this->is_bone(pNode))

{

return -1;

}

//遍历骨骼数组查找该节点是否存在其中

for(int i=0; i < m_bones.size(); ++i)

{

if(m_bones.at(i).pNode == pNode)

{

return i;

}

}

return -1;

}

int Export_Mesh::get_bone_index(INode* pNode)

{

//测试该节点是否为骨骼节点

if(!this->is_bone(pNode))

{

return -1;

}

//遍历骨骼数组查找该节点是否存在其中

for(int i=0; i < m_bones.size(); ++i)

{

if(m_bones.at(i).pNode == pNode)

{

return i;

}

}

return -1;

}

接下来是读取权重信息.先看看load_bone_weights函数的实现:

view plaincopy to clipboardprint?

bool Export_Mesh::load_bone_weights(INode* pNode)

{

if((!pNode)||(!this->is_mesh(pNode))) return false;

//尝试取得体形变形器

Modifier* pmf = this->get_mod(pNode, Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B));

if(pmf)//如果取得成功

{

//设置权重顶点尺寸

this->get_physique_weights(pNode, pmf);

}

else//如果没有,尝试取得皮肤变形器

{

pmf = this->get_mod(pNode, SKIN_CLASSID);

if(pmf)

{

this->get_skin_weights(pNode, pmf);

}

}

//递归处理子节点

const int childCnt = pNode->NumberOfChildren();

for(int i = 0; i < childCnt; ++i)

{

this->load_bone_weights(pNode->GetChildNode(i));

}

return true;

}

bool Export_Mesh::load_bone_weights(INode* pNode)

{

if((!pNode)||(!this->is_mesh(pNode))) return false;

//尝试取得体形变形器

Modifier* pmf = this->get_mod(pNode, Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B));

if(pmf)//如果取得成功

{

//设置权重顶点尺寸

this->get_physique_weights(pNode, pmf);

}

else//如果没有,尝试取得皮肤变形器

{

pmf = this->get_mod(pNode, SKIN_CLASSID);

if(pmf)

{

this->get_skin_weights(pNode, pmf);

}

}

//递归处理子节点

const int childCnt = pNode->NumberOfChildren();

for(int i = 0; i < childCnt; ++i)

{

this->load_bone_weights(pNode->GetChildNode(i));

}

return true;

}

在3dmax中,骨骼动画可能由常规的皮肤构造,也可以由character studio构造(好吧,我承认我是猜的.实际上我基本没用过3dmax).因此一个带有骨骼动画的模型节点可能存在两种变形器:体形变形器和皮肤变形器.要导出权重就需要变形器对象.下面看看取得变形器使用的函数:

view plaincopy to clipboardprint?

Modifier* Export_Mesh::get_mod(INode* pNode, Class_ID id)

{

Object* pObj = pNode->GetObjectRef();

if(!pObj) return NULL;

//是否是个导出对象

while(pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID)

{

//如果是导出对象

IDerivedObject* pDerivedObj = static_cast<IDerivedObject*>(pObj);

//循环变形器堆栈上的所有实体

for(int i=0; i<pDerivedObj->NumModifiers(); ++i)

{

//取得当前的变形器

Modifier* pMod = pDerivedObj->GetModifier(i);

//是否是体形?

if(pMod->ClassID() == id)

{

return pMod;

}

}

pObj = pDerivedObj->GetObjRef();

}

//没有找到

return NULL;

}

Modifier* Export_Mesh::get_mod(INode* pNode, Class_ID id)

{

Object* pObj = pNode->GetObjectRef();

if(!pObj) return NULL;

//是否是个导出对象

while(pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID)

{

//如果是导出对象

IDerivedObject* pDerivedObj = static_cast<IDerivedObject*>(pObj);

//循环变形器堆栈上的所有实体

for(int i=0; i<pDerivedObj->NumModifiers(); ++i)

{

//取得当前的变形器

Modifier* pMod = pDerivedObj->GetModifier(i);

//是否是体形?

if(pMod->ClassID() == id)

{

return pMod;

}

}

pObj = pDerivedObj->GetObjRef();

}

//没有找到

return NULL;

}

这个函数没有什么好解释的,就是检查下ClassID的工作.

下面是重点,从变形器中取出顶点在各个骨骼上的权重,先看下取得形体变形器的get_physique_weights:

view plaincopy to clipboardprint?

void Export_Mesh::get_physique_weights(INode* pNode, Modifier* pMod)

{

//为变形器创建一个体形导出接口

IPhysiqueExport* phyInterface = (IPhysiqueExport*)pMod->GetInterface(I_PHYINTERFACE);

if(!phyInterface) return;

//为指定节点创建一个ModContext导出接口

IPhyContextExport* modContextInt =

(IPhyContextExport*)phyInterface->GetContextInterface(pNode);

if(modContextInt)

{

//需要顶点接口(现在只支持刚体)

modContextInt->ConvertToRigid(TRUE);

//允许每个节点超过一个骨骼

modContextInt->AllowBlending(TRUE);

const int totalVtx = modContextInt->GetNumberVertices();//取得总顶点数

//调整权重顶点的尺寸

assert(m_weight_vertexs.size() == 0);

m_weight_vertexs.resize(totalVtx);

for(int i = 0; i < totalVtx; ++i)//遍历所有的顶点

{

//取得顶点导出器的接口

IPhyVertexExport* vtxInterface =

(IPhyVertexExport*)modContextInt->GetVertexInterface(i);

if(!vtxInterface) continue;

int vtxType = vtxInterface->GetVertexType();

if(RIGID_TYPE == vtxType)//只受一块骨骼影响,权重为1

{

//取得骨骼节点

INode* boneNode = ((IPhyRigidVertex*)vtxInterface)->GetNode();

int boneIdx = this->get_bone_index(boneNode);

//设置骨骼权重

m_weight_vertexs.at(i)[boneIdx] = 1.0f;

}

else if(RIGID_BLENDED_TYPE == vtxType)//受多块骨骼影响

{

IPhyBlendedRigidVertex* vtxBlendedInt =

(IPhyBlendedRigidVertex*)vtxInterface;

assert(vtxBlendedInt);

for(int j = 0; j < vtxBlendedInt->GetNumberNodes(); ++j)

{

INode* boneNode = vtxBlendedInt->GetNode(j);

int boneIdx = this->get_bone_index(boneNode);

//查找此权重顶点中是否存在此骨骼的权重

Weight_Vertx::iterator fpos = m_weight_vertexs.at(i).find(boneIdx);

if(fpos == m_weight_vertexs.at(i).end())//如果不存在

{

//则向当前骨骼的权重列表中添加新的一项

m_weight_vertexs.at(i)[boneIdx] = vtxBlendedInt->GetWeight(j);

}

else//如果存在

{

//则累加上当前骨骼的权重

fpos->second += vtxBlendedInt->GetWeight(j);

}

}

}

}

phyInterface->ReleaseContextInterface(modContextInt);

}

pMod->ReleaseInterface(I_PHYINTERFACE, phyInterface);

}

void Export_Mesh::get_physique_weights(INode* pNode, Modifier* pMod)

{

//为变形器创建一个体形导出接口

IPhysiqueExport* phyInterface = (IPhysiqueExport*)pMod->GetInterface(I_PHYINTERFACE);

if(!phyInterface) return;

//为指定节点创建一个ModContext导出接口

IPhyContextExport* modContextInt =

(IPhyContextExport*)phyInterface->GetContextInterface(pNode);

if(modContextInt)

{

//需要顶点接口(现在只支持刚体)

modContextInt->ConvertToRigid(TRUE);

//允许每个节点超过一个骨骼

modContextInt->AllowBlending(TRUE);

const int totalVtx = modContextInt->GetNumberVertices();//取得总顶点数

//调整权重顶点的尺寸

assert(m_weight_vertexs.size() == 0);

m_weight_vertexs.resize(totalVtx);

for(int i = 0; i < totalVtx; ++i)//遍历所有的顶点

{

//取得顶点导出器的接口

IPhyVertexExport* vtxInterface =

(IPhyVertexExport*)modContextInt->GetVertexInterface(i);

if(!vtxInterface) continue;

int vtxType = vtxInterface->GetVertexType();

if(RIGID_TYPE == vtxType)//只受一块骨骼影响,权重为1

{

//取得骨骼节点

INode* boneNode = ((IPhyRigidVertex*)vtxInterface)->GetNode();

int boneIdx = this->get_bone_index(boneNode);

//设置骨骼权重

m_weight_vertexs.at(i)[boneIdx] = 1.0f;

}

else if(RIGID_BLENDED_TYPE == vtxType)//受多块骨骼影响

{

IPhyBlendedRigidVertex* vtxBlendedInt =

(IPhyBlendedRigidVertex*)vtxInterface;

assert(vtxBlendedInt);

for(int j = 0; j < vtxBlendedInt->GetNumberNodes(); ++j)

{

INode* boneNode = vtxBlendedInt->GetNode(j);

int boneIdx = this->get_bone_index(boneNode);

//查找此权重顶点中是否存在此骨骼的权重

Weight_Vertx::iterator fpos = m_weight_vertexs.at(i).find(boneIdx);

if(fpos == m_weight_vertexs.at(i).end())//如果不存在

{

//则向当前骨骼的权重列表中添加新的一项

m_weight_vertexs.at(i)[boneIdx] = vtxBlendedInt->GetWeight(j);

}

else//如果存在

{

//则累加上当前骨骼的权重

fpos->second += vtxBlendedInt->GetWeight(j);

}

}

}

}

phyInterface->ReleaseContextInterface(modContextInt);

}

pMod->ReleaseInterface(I_PHYINTERFACE, phyInterface);

}

我想代码的注释已经很清楚了,没有必要解释了吧?get_skin_weights函数基本和上面那个是一样的:

view plaincopy to clipboardprint?

void Export_Mesh::get_skin_weights(INode* pNode, Modifier* pMod)

{

//为变形器创建一个皮肤导出接口

ISkin* skin = (ISkin*)pMod->GetInterface(I_SKIN);

if(!skin) return;

//为指定节点创建一个皮肤上下文

ISkinContextData* skincontext = skin->GetContextInterface(pNode);

if(skincontext)

{

//遍历所有顶点,取得权重

const int numVert = skincontext->GetNumPoints();

//调整权重顶点的尺寸

assert(m_weight_vertexs.size() == 0);

m_weight_vertexs.resize(numVert);

for(int i = 0; i < numVert; ++i)

{

const int numBones = skincontext->GetNumAssignedBones(i);

for(int j = 0; j < numBones; ++j)

{

INode* bone = skin->GetBone(skincontext->GetAssignedBone(i,j));//do not use j,but use GetAssignedBone(i,j)

if(!bone) continue;

int boneIdx = this->get_bone_index(bone);

if(-1 == boneIdx) continue;

//查找此权重顶点中是否存在此骨骼的权重

Weight_Vertx::iterator fpos = m_weight_vertexs.at(i).find(boneIdx);

if(fpos == m_weight_vertexs.at(i).end())//如果不存在

{

//则向当前骨骼的权重列表中添加新的一项

m_weight_vertexs.at(i)[boneIdx] = skincontext->GetBoneWeight(i,j);

}

else//如果存在

{

//则累加上当前骨骼的权重

fpos->second += skincontext->GetBoneWeight(i,j);

}

}

}

}

pMod->ReleaseInterface(I_SKIN, skin);

}

void Export_Mesh::get_skin_weights(INode* pNode, Modifier* pMod)

{

//为变形器创建一个皮肤导出接口

ISkin* skin = (ISkin*)pMod->GetInterface(I_SKIN);

if(!skin) return;

//为指定节点创建一个皮肤上下文

ISkinContextData* skincontext = skin->GetContextInterface(pNode);

if(skincontext)

{

//遍历所有顶点,取得权重

const int numVert = skincontext->GetNumPoints();

//调整权重顶点的尺寸

assert(m_weight_vertexs.size() == 0);

m_weight_vertexs.resize(numVert);

for(int i = 0; i < numVert; ++i)

{

const int numBones = skincontext->GetNumAssignedBones(i);

for(int j = 0; j < numBones; ++j)

{

INode* bone = skin->GetBone(skincontext->GetAssignedBone(i,j));//do not use j,but use GetAssignedBone(i,j)

if(!bone) continue;

int boneIdx = this->get_bone_index(bone);

if(-1 == boneIdx) continue;

//查找此权重顶点中是否存在此骨骼的权重

Weight_Vertx::iterator fpos = m_weight_vertexs.at(i).find(boneIdx);

if(fpos == m_weight_vertexs.at(i).end())//如果不存在

{

//则向当前骨骼的权重列表中添加新的一项

m_weight_vertexs.at(i)[boneIdx] = skincontext->GetBoneWeight(i,j);

}

else//如果存在

{

//则累加上当前骨骼的权重

fpos->second += skincontext->GetBoneWeight(i,j);

}

}

}

}

pMod->ReleaseInterface(I_SKIN, skin);

}

最后要导出整个模型的全部信息,就冲根节点开始递归遍历所有节点进行导出工作:

view plaincopy to clipboardprint?

void Export_Mesh::export_mesh(INode* pNode)

{

if(this->is_mesh(pNode))

{

this->load_bone_weights(pNode);

}

//递归遍历所有的模型子节点

for(int i = 0; i < pNode->NumberOfChildren(); ++i)

{

this->export_mesh(pNode->GetChildNode(i));

}

}

void Export_Mesh::export_mesh(INode* pNode)

{

if(this->is_mesh(pNode))

{

this->load_bone_weights(pNode);

}

//递归遍历所有的模型子节点

for(int i = 0; i < pNode->NumberOfChildren(); ++i)

{

this->export_mesh(pNode->GetChildNode(i));

}

}

现在终于把骨骼动画的信息按照我需要的格式放进内存了.为了看下导出的效果,输出到文本文件:

view plaincopy to clipboardprint?

bool Export_Mesh::export_file(const TCHAR* name)

{

std::ofstream outfile(name);

//先读取骨架信息

this->load_bone_struct(pRoot, -1);

//遍历所有的模型节点,读出权重信息

this->export_mesh(m_root);

//输出骨架信息

outfile << "Bone Information: " << m_bones.size() << "/n";

for(int i = 0; i < m_bones.size(); ++i)

{

outfile << "Bone Index: " << i << "/n"

<< "Bone id: " << (void*)(m_bones.at(i).pNode) << "/n"

<< "Parent Index: " << m_bones.at(i).parent << "/n"

<< "Childs Index: ";

for( Bone::Child_Vec::iterator j = m_bones.at(i).childs.begin();

j != m_bones.at(i).childs.end(); ++j )

{

outfile << *j << " ";

}

outfile << "/n=======================================================/n";

}

outfile << "Bone Weights: " << m_weight_vertexs.size() << "/n";

for(int i = 0; i < m_weight_vertexs.size(); ++i)

{

outfile << "Vertex Index:" << i << "/n";

for(Weight_Vertx::iterator j = m_weight_vertexs.at(i).begin();

j != m_weight_vertexs.at(i).end(); ++j)

{

outfile << "/tBone Index:" << j->first << "; Weight: " << j->second << "/n";

}

outfile << "/n=======================================================/n";

}

outfile.flush();

outfile.close();

return true;

}

bool Export_Mesh::export_file(const TCHAR* name)

{

std::ofstream outfile(name);

//先读取骨架信息

this->load_bone_struct(pRoot, -1);

//遍历所有的模型节点,读出权重信息

this->export_mesh(m_root);

//输出骨架信息

outfile << "Bone Information: " << m_bones.size() << "/n";

for(int i = 0; i < m_bones.size(); ++i)

{

outfile << "Bone Index: " << i << "/n"

<< "Bone id: " << (void*)(m_bones.at(i).pNode) << "/n"

<< "Parent Index: " << m_bones.at(i).parent << "/n"

<< "Childs Index: ";

for( Bone::Child_Vec::iterator j = m_bones.at(i).childs.begin();

j != m_bones.at(i).childs.end(); ++j )

{

outfile << *j << " ";

}

outfile << "/n=======================================================/n";

}

outfile << "Bone Weights: " << m_weight_vertexs.size() << "/n";

for(int i = 0; i < m_weight_vertexs.size(); ++i)

{

outfile << "Vertex Index:" << i << "/n";

for(Weight_Vertx::iterator j = m_weight_vertexs.at(i).begin();

j != m_weight_vertexs.at(i).end(); ++j)

{

outfile << "/tBone Index:" << j->first << "; Weight: " << j->second << "/n";

}

outfile << "/n=======================================================/n";

}

outfile.flush();

outfile.close();

return true;

}

最后一步,在3dmax导出插件中让它起作用:

view plaincopy to clipboardprint?

int pge_3dmax_exporter::DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts, DWORD options)

{

Export_Mesh export_mesh(i->GetRootNode());

export_mesh.export_file(name);

return TRUE;

}

int pge_3dmax_exporter::DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts, DWORD options)

{

Export_Mesh export_mesh(i->GetRootNode());

export_mesh.export_file(name);

return TRUE;

}

最终输出的文本文件如下:

Bone Information: 32

Bone Index: 0

Bone id: 08CC6CB0

Parent Index: -1

Childs Index: 1

=======================================================

Bone Index: 1

Bone id: 08CC33A0

Parent Index: 0

Childs Index: 2

=======================================================

......

Bone Weights: 462

Vertex Index:0

Bone Index:26; Weight: 1

=======================================================

Vertex Index:1

Bone Index:7; Weight: 0.999999

Bone Index:18; Weight: 1.01289e-006

=======================================================

Vertex Index:2

Bone Index:5; Weight: 9.13872e-006

Bone Index:7; Weight: 0.999991

转自:http://blog.csdn.net/s_51563946/article/details/4458341
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: