导出整个网格,先不管材质等其他信息,结合以前的程序,下面是导出的主程序,这个主程序能导出一个没有后缀名的文件(加上后缀名.mesh就能被ogre meshy识别)。该文件用ogre meshy打开后,能显示出3DS Max中的一个mesh。
int OgreMaxExport::DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts, DWORD options)
{
m_pMaxScene = GetIGameInterface();
IGameConversionManager *pConMan = GetConversionManager();
pConMan->SetCoordSystem (IGameConversionManager::IGAME_OGL);
m_pMaxScene->SetPropertyFile("IGameProp.xml");
m_pMaxScene->InitialiseIGame(false);
m_iNodeCount = m_pMaxScene->GetTopLevelNodeCount();
if (m_iNodeCount == 0)
{
MessageBox (NULL, "No node in current scene", "Max plug-in", MB_OK);
return 0;
}
//
IGameNode* pNode = m_pMaxScene->GetTopLevelNode(0);
IGameObject* pObject = pNode->GetIGameObject();
IGameObject::ObjectTypes type = pObject->GetIGameType();
IGameMaterial* mtl = pNode->GetNodeMaterial();
int iFaceCount, iVertexCount;
if (type == IGameObject::IGAME_MESH)
{
IGameMesh* pMesh = (IGameMesh*) pObject;
if (!pMesh->IsEntitySupported())
{
MessageBox (NULL, "Entity not supported", "Max plug-in", MB_OK);
return 0;
}
if (!pMesh->InitializeData())
{
MessageBox (NULL, "Mesh InitializeData() failed!", "Max plug-in", MB_OK);
return 0;
}
iVertexCount = pMesh->GetNumberOfVerts();
iFaceCount = pMesh->GetNumberOfFaces();
Tab<int> texMap = pMesh->GetActiveMapChannelNum();
TiXmlDocument *pXmlDoc = new TiXmlDocument();
char stub[128];
TiXmlDeclaration* declarationElem = new TiXmlDeclaration(_T("1.0"), _T(""), _T(""));
pXmlDoc->LinkEndChild(declarationElem);
TiXmlElement* meshElem = new TiXmlElement("mesh");
pXmlDoc->LinkEndChild(meshElem);
// <submeshes> </submeshes>
TiXmlElement* submeshes = new TiXmlElement("submeshes");
meshElem->LinkEndChild(submeshes);
// <submesh> </submesh>
TiXmlElement* submesh = new TiXmlElement("submesh");
submeshes->LinkEndChild(submesh);
if (mtl != NULL)
submesh->SetAttribute("material", mtl->GetMaterialName());
else
submesh->SetAttribute("material", "");
submesh->SetAttribute("usesharedvertices", "false");
submesh->SetAttribute("use32bitindexes", 0);
// <faces> </faces>
TiXmlElement* faces = new TiXmlElement("faces");
submesh->LinkEndChild(faces);
faces->SetAttribute("count", iFaceCount);
int index = 0;
for (index = 0; index < iFaceCount; index++)
{
TiXmlElement* face = new TiXmlElement("face");
faces->LinkEndChild(face);
FaceEx* pFace = pMesh->GetFace(index);
for (int i = 0; i < 3; i++)
{
// vertex
Point3 vertex = pMesh->GetVertex(pFace->vert[i]);
m_vertexVector.push_back(vertex);
// vertex color (diffuse)
Point3 diffuse = pMesh->GetColorVertex(pFace->vert[i]);
float alpha = pMesh->GetAlphaVertex(pFace->vert[i]);
m_diffuseVector.push_back(diffuse);
m_alphaVector.push_back(alpha);
Point3 normal = pMesh->GetNormal(pFace, i);
m_normalVector.push_back(normal);
DWORD idx[3];
Point3 tv;
for (int ch = 0; ch < texMap.Count(); ch++)
{
if (pMesh->GetMapFaceIndex(texMap[ch], index, idx))
tv = pMesh->GetMapVertex(texMap[ch], idx[i]);
else
tv = pMesh->GetMapVertex(texMap[ch], pFace->vert[i]);
m_tvMap.insert(pair<int, Point3>(texMap[ch], tv));
}
memset(stub, 0, 128);
sprintf (stub, "v%d", i+1);
face->SetAttribute(stub, m_vertexVector.size() - 1);
}
}
TiXmlElement* geometry = new TiXmlElement("geometry");
submesh->LinkEndChild(geometry);
geometry->SetAttribute("vertexcount", iVertexCount);
TiXmlElement* vertexbuffer = new TiXmlElement("vertexbuffer");
geometry->LinkEndChild(vertexbuffer);
vertexbuffer->SetAttribute("positions", "true");
vertexbuffer->SetAttribute("normals", "false");
vertexbuffer->SetAttribute("colours_diffuse", "false");
vertexbuffer->SetAttribute("texture_coords", texMap.Count());
for (index = 0; index < texMap.Count(); index++)
{
memset(stub, 0, 128);
sprintf(stub, "texture_coords_dimension_%d", index);
vertexbuffer->SetAttribute(stub, "2");
}
std::vector<Point3>::size_type ii = m_vertexVector.size();
for (ii = 0; ii < m_vertexVector.size(); ii++)
{
TiXmlElement* vertex = new TiXmlElement("vertex");
vertexbuffer->LinkEndChild(vertex);
// position
TiXmlElement* position = new TiXmlElement("position");
vertex->LinkEndChild(position);
Point3 pos = (Point3) m_vertexVector.at(ii);
position->SetDoubleAttribute("x", pos.x);
position->SetDoubleAttribute("y", pos.y);
position->SetDoubleAttribute("z", pos.z);
// vertex color (diffuse)
TiXmlElement* colour_diffuse = new TiXmlElement("colour_diffuse");
vertex->LinkEndChild(colour_diffuse);
Point3 diffuse = m_diffuseVector.at(ii);
memset(stub, 0, 128);
sprintf(stub, " %f %f %f", diffuse.x, diffuse.y, diffuse.z);
colour_diffuse->SetAttribute("value", stub);
// vertex normal
TiXmlElement* normal = new TiXmlElement("normal");
vertex->LinkEndChild(normal);
Point3 vertexNormal = m_normalVector.at(ii);
normal->SetDoubleAttribute("x", vertexNormal.x);
normal->SetDoubleAttribute("y", vertexNormal.y);
normal->SetDoubleAttribute("z", vertexNormal.z);
}
pXmlDoc->SaveFile(name);
delete pXmlDoc;
}
return 1;
}
需要注意的地方是:
1、C++的new的操作符在堆上创建相关对象,一般我们显式创建的对象,需要我们自己显式调用delete个来删除。但是用TinyXML的时候,这部分东西是TinyXML自己管理的,所以不用自己用delete,否则会出错;
2、ogre的顶点格式导出的时候,下标从1开始,不是0;否则会出错。这是我们这句代码的原因:
sprintf (stub, "v%d", i+1);
最后,这个是导出的茶壶的mesh用ogre meshy打开后的结果: