摘要:本篇3Dmax教程探讨了使用3Dmax导出插件导出模型信息,希望阅读本篇文章以后大家有所收获,帮助大家对3Dmax的掌握更加熟练。
首先定义骨骼的结构:
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
本文由职坐标整理发布,欢迎关注职坐标3Dmax频道,学习更多相关知识!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号