Esempio n. 1
0
void MeshExporter::ExtractMesh(IGameNode * node)
{
	IGameObject* obj = node->GetIGameObject();

	// export option
	bool expColor = ExportConfig::Instance()->IsExportColor();
	bool expNormal = ExportConfig::Instance()->IsExportNormal();
	bool expTexcoord = ExportConfig::Instance()->IsExportTexcoord();
	bool expLightmapUV = ExportConfig::Instance()->IsExportLightmapUV();

	obj->InitializeData();

	const char * nodeName = node->GetName();

	IGameNode * parent = node->GetNodeParent();
	IGameMesh::ObjectTypes type = obj->GetIGameType();

	if (type == IGameMesh::IGAME_MESH)
	{
		IGameMesh* mesh = (IGameMesh*) obj;
		Tab<int> texMaps = mesh->GetActiveMapChannelNum();

		mMeshData.VertexElems |= MeshSerializer::VE_POSITION;

		// position
		for (int i = 0; i < mesh->GetNumberOfVerts(); ++i)
			mMeshData.P.PushBack(Utility::ToFloat3(mesh->GetVertex(i)));

		// vertex color
		for (int i = 0; expColor && i < mesh->GetNumberOfColorVerts(); ++i)
		{
			Point3 c = mesh->GetColorVertex(i);
			float a = mesh->GetAlphaVertex(i);

			mMeshData.C.PushBack(Float4(c.x, c.y, c.z, a));
			mMeshData.VertexElems |= MeshSerializer::VE_COLOR;
		}

		// normal
		for (int i = 0; expNormal && i < mesh->GetNumberOfNormals(); ++i)
		{
			mMeshData.N.PushBack(Utility::ToFloat3(mesh->GetNormal(i)));
			mMeshData.VertexElems |= MeshSerializer::VE_NORMAL;
		}

		// uv
		for (int i = 0;  expTexcoord && texMaps.Count() > 1 && i < mesh->GetNumberOfMapVerts(texMaps[1]); ++i)
		{
			Point3 tv = mesh->GetMapVertex(texMaps[1], i);

			mMeshData.UV.PushBack(Float2(tv.x, 1 - tv.y));
			mMeshData.VertexElems |= MeshSerializer::VE_TEXCOORD;
		}

		// light map uv
		for (int i = 0;  expLightmapUV && texMaps.Count() > 2 && i < mesh->GetNumberOfMapVerts(texMaps[2]); ++i)
		{
			Point3 tv = mesh->GetMapVertex(texMaps[2], i);

			mMeshData.LUV.PushBack(Float2(tv.x, 1 - tv.y));
			mMeshData.VertexElems |= MeshSerializer::VE_LIGHTMAPUV;
		}

		IGameSkin * skin = obj->GetIGameSkin();
		if (skin != NULL)
			_dumpSkinInfo(skin);
		else if (parent != NULL && parent->GetIGameObject()->GetIGameType() == IGameMesh::IGAME_BONE)
			_genSkinInfo(parent);

		_dumpMeshBuffer(mesh);

		mMeshData.Clear();
	}

	for(int i=0;i<node->GetChildCount();i++)
	{
		IGameNode * child = node->GetNodeChild(i);
		// we deal with targets in the light/camera section
		if(child->IsTarget())
			continue;

		ExtractMesh(child);
	}

	node->ReleaseIGameObject();
}
	bool MeshXMLExporter::Export(OutputMap& output) 
	{

		try {

			// write XML to a strstream
			std::stringstream of;

			while (!m_submeshNames.empty())
				m_submeshNames.pop();

			if (m_pGame) {
				m_pGame->ReleaseIGame();
				m_pGame = 0;
			}

			m_ei->theScene->EnumTree(this);

			m_pGame = GetIGameInterface();
			IGameConversionManager* cm = GetConversionManager();
			cm->SetCoordSystem(IGameConversionManager::IGAME_OGL);
			m_pGame->InitialiseIGame(m_nodeTab, false);
			m_pGame->SetStaticFrame(0);
			int nodeCount = m_pGame->GetTopLevelNodeCount();

			if (nodeCount == 0) {
				MessageBox(GetActiveWindow(), "No nodes available to export, aborting...", "Nothing To Export", MB_ICONINFORMATION);
				m_pGame->ReleaseIGame();
				return false;
			}

			// if we are writing everything to one file, use the name provided when the user first started the export;
			// otherwise, create filenames on the basis of the node (submesh) names
			std::string fileName;
			IGameNode* node = m_pGame->GetTopLevelNode(0);
			if (!m_config.getExportMultipleFiles())
				fileName = m_config.getExportFilename();
			else {
				fileName = m_config.getExportPath() + "\\";
				fileName += node->GetName();
				fileName += ".mesh.xml";
			}

			// write start of XML data
			streamFileHeader(of);

			int nodeIdx = 0;
			std::map<std::string, std::string> materialScripts;

			while (nodeIdx < nodeCount) {

				std::string mtlName;
				IGameNode* node = m_pGame->GetTopLevelNode(nodeIdx);
				IGameObject* obj = node->GetIGameObject();

				// InitializeData() is important -- it performs all of the WSM/time eval for us; no data without it
				obj->InitializeData();
				
				IGameMaterial* mtl = node->GetNodeMaterial();
				if (mtl == NULL)
					mtlName = m_config.getDefaultMaterialName();
				else
					mtlName = mtl->GetMaterialName();

				// clean out any spaces the user left in their material name
				std::string::size_type pos;
				while ((pos = mtlName.find_first_of(' ')) != std::string::npos)
					mtlName.replace(pos, 1, _T("_"));

				if (materialScripts.find(mtlName) == materialScripts.end()) {

					// export new material script
					MaterialExporter mexp(m_config, m_materialMap);
					std::string script;

					mexp.buildMaterial(mtl, mtlName, script);
					materialScripts[mtlName] = script;
				}

				//if (streamSubmesh(of, node, mtlName))
				if (streamSubmesh(of, obj, mtlName))
					m_submeshNames.push(std::string(node->GetName()));

				node->ReleaseIGameObject();
				nodeIdx++;

				if (m_config.getExportMultipleFiles() || nodeIdx == nodeCount) {

					// write end of this file's XML
					streamFileFooter(of);

					// insert new filename --> stream pair into output map
					output[fileName] = std::string(of.str());
					of.str("");

					if (nodeIdx != nodeCount) {
						fileName = m_config.getExportPath() + "\\";
						node = m_pGame->GetTopLevelNode(nodeIdx);
						fileName += node->GetName();
						fileName += ".mesh.xml";

						// start over again with new data
						streamFileHeader(of);
					}
				}
			}

			m_pGame->ReleaseIGame();

			// export materials if we are writing those
			if (m_config.getExportMaterial()) {

				std::ofstream materialFile;
				materialFile.open((m_config.getExportPath() + "\\" + m_config.getMaterialFilename()).c_str(), std::ios::out);

				if (materialFile.is_open()) {
					for (std::map<std::string, std::string>::iterator it = materialScripts.begin();
						it != materialScripts.end(); ++it)
					{
						materialFile << it->second;
					}

					materialFile.close();
				}
			}

			return true;
		}
		catch (...) {
			MessageBox(GetActiveWindow(), "An unexpected error has occurred while trying to export, aborting", "Error", MB_ICONEXCLAMATION);

			if (m_pGame)
				m_pGame->ReleaseIGame();

			return false;
		}
	}
Esempio n. 3
0
//[-------------------------------------------------------]
//[ Private virtual PLSceneNode functions                 ]
//[-------------------------------------------------------]
void PLSceneSpline::WriteToFile(XmlElement &cSceneElement, const String &sApplicationDrive, const String &sApplicationDir)
{
	// Do NOT save it as scene node, it's just a 'resource'

	// Get path filename
	const String sFilename = sApplicationDrive + sApplicationDir + PLTools::GetResourceFilename(PLTools::ResourcePath, GetName() + ".path");

	// Get the IGame spline object of the given IGame node
	IGameObject *pIGameObject = GetIGameNode()->GetIGameObject();
	if (pIGameObject) {
		// Check the type of the IGame object
		if (pIGameObject->GetIGameType() == IGameObject::IGAME_SPLINE && pIGameObject->InitializeData()) {
			IGameSpline &cIGameSpline = *static_cast<IGameSpline*>(pIGameObject);
			if (cIGameSpline.GetNumberOfSplines () > 0) {
				// We only support spline 0
				IGameSpline3D *pIGameSpline3D = cIGameSpline.GetIGameSpline3D(0);
				if (pIGameSpline3D) {
					// Get the local transform matrix
					GMatrix mTransform = cIGameSpline.GetIGameObjectTM();

					// Get the 3ds Max shape object
					ShapeObject *pMaxShapeObject = static_cast<ShapeObject*>(pIGameObject->GetMaxObject()->ConvertToType(TIME_PosInfinity, Class_ID(GENERIC_SHAPE_CLASS_ID, 0)));
					if (pMaxShapeObject != nullptr && pMaxShapeObject->NumberOfCurves() == cIGameSpline.GetNumberOfSplines()) {
						// Create XML document
						XmlDocument cDocument;

						// Add declaration
						XmlDeclaration *pDeclaration = new XmlDeclaration("1.0", "ISO-8859-1", "");
						cDocument.LinkEndChild(*pDeclaration);

						// Add path
						XmlElement *pPathElement = new XmlElement("Path");

						// Setup attributes
						pPathElement->SetAttribute("Version", "1");
						pPathElement->SetAttribute("Closed",  String::Format("%d", pMaxShapeObject->CurveClosed(0, 0)));

						// Add all nodes
						for (int nKnot=0; nKnot<pIGameSpline3D->GetIGameKnotCount(); nKnot++) {
							IGameKnot *pIGameKnot = pIGameSpline3D->GetIGameKnot(nKnot);
							if (pIGameKnot) {
								// Get knot point in object space (although it is not documented it looks like object space...)
								Point3 cPoint = pIGameKnot->GetKnotPoint();

								// We really need to flip the coordinates to OpenGL style, IGame is not doing this automatically...
								cPoint = PLTools::Convert3dsMaxVectorToOpenGLVector(cPoint);

								// Transform to world space
								cPoint = cPoint*mTransform;

								// If there's a parent container, make the position of this scene node relative to it
								PLSceneContainer *pContainer = GetContainer();
								if (pContainer)
									cPoint -= pContainer->GetWorldSpaceCenter();

								// Add node
								XmlElement *pNodeElement = new XmlElement("Node");
								pNodeElement->SetAttribute("Name",     String::Format("%d",       nKnot));
								pNodeElement->SetAttribute("Position", String::Format("%f %f %f", cPoint.x, cPoint.y, cPoint.z));

								// Link general element
								pPathElement->LinkEndChild(*pNodeElement);
							}
						}

						// Link material element
						cDocument.LinkEndChild(*pPathElement);

						// Save settings
						if (cDocument.Save(sFilename))
							g_pLog->LogFLine(PLLog::Hint, "Created '%s'", sFilename.GetASCII());
						else
							g_pLog->LogFLine(PLLog::Error, "Can't create '%s'!", sFilename.GetASCII());
					}
				}
			}
		} else {
			g_pLog->LogFLine(PLLog::Error, "%s: IGame object is no known spline object!", GetIGameNode()->GetName());
		}

		// Release the IGame object
		GetIGameNode()->ReleaseIGameObject();
	} else {
		g_pLog->LogFLine(PLLog::Error, "%s: IGame node has no IGame object!", GetIGameNode()->GetName());
	}
}