HRESULT ParaEngine::CParaXProcessor::CopyToResource()
{
	if (m_asset.get() == 0)
		return E_FAIL;
	if (m_asset->m_MeshLODs.size() == 0)
	{
		string filename = m_asset->GetLocalFileName();

		bool bLoadHeaderFromXFile = true;
		bool bSingleLOD = true;
		bool bIsXML = (CParaFile::GetFileExtension(filename) == "xml");
		string sParentDirectory = CParaFile::GetParentDirectoryFromPath(filename);


		// check in manifest
		AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(filename);
		if (pEntry)
		{
			if (pEntry->DoesFileExist())
			{
				filename = pEntry->GetLocalFileName();
			}
			else
			{
				m_pAssetFileEntry = pEntry;
				return E_PENDING;
			}
		}

		if (bIsXML)
		{
			CParaMeshXMLFile file;
			if (file.LoadFromFile(filename, sParentDirectory))
			{
				if (file.GetType() == CParaMeshXMLFile::TYPE_MESH_LOD)
				{
					int i;
					// check if all sub files are available locally.
					for (i = 0; i < file.GetSubMeshCount(); ++i)
					{
						CParaMeshXMLFile::CSubMesh* pSubLODMesh = file.GetSubMesh(i);
						AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(pSubLODMesh->m_sFileName);
						if (pEntry)
						{
							if (pEntry->DoesFileExist())
							{
								pSubLODMesh->m_sFileName = pEntry->GetLocalFileName();
							}
							else
							{
								m_pAssetFileEntry = pEntry;
								return E_PENDING;
							}
						}
					}

					if (file.m_bHasBoundingBox)
					{
					}

					for (i = 0; i < file.GetSubMeshCount(); ++i)
					{
						CParaMeshXMLFile::CSubMesh* pSubLODMesh = file.GetSubMesh(i);
						CreateMeshLODLevel(pSubLODMesh->m_fToCameraDist, pSubLODMesh->m_sFileName);
					}
					if (file.GetSubMeshCount() == 0)
					{
						OUTPUT_LOG("warning: LOD file %s does not contain any lod mesh references\n", filename.c_str());
						return E_FAIL;
					}
				}
			}
			else
			{
				OUTPUT_LOG("failed loading mesh xml file: %s\n", filename.c_str());
				return E_FAIL;
			}
		}
		else
		{
			CreateMeshLODLevel(0.f, filename);
		}
	}

	try
	{
		// preload file data to memory in the IO thread. 
		std::vector<MeshLOD> & pMeshLODs = m_MeshLODs.size() > 0 ? m_MeshLODs : m_asset->m_MeshLODs;
		for (auto iCur = pMeshLODs.begin(); iCur != pMeshLODs.end(); ++iCur)
		{
			if ( ! (iCur->m_pParaXMesh) )
			{
				CParaFile myFile(iCur->m_sMeshFileName.c_str());

				if (myFile.isEof())
				{
					OUTPUT_LOG("warning: ParaX model file not found %s\n", iCur->m_sMeshFileName.c_str());
					return E_FAIL;
				}

				std::string sExt = CParaFile::GetFileExtension(iCur->m_sMeshFileName);
				StringHelper::make_lower(sExt);
				if (sExt == "bmax")
				{
					// block max model. 
					BMaxParser p(myFile.getBuffer(), myFile.getSize());
					iCur->m_pParaXMesh = p.ParseParaXModel();
					auto pParaXMesh = iCur->m_pParaXMesh;

#ifdef ENABLE_BMAX_AUTO_LOD
					if (m_MeshLODs.size() == 1)
					{
						// each LOD at least cut triangle count in half and no bigger than a given count. 
						// by default, generate lod in range 30, 60, 90, 120 meters;
						// TODO: currently it is hard-coded, shall we read LOD settings from bmax file, so that users
						// have find-control on the settings. 
						struct LODSetting {
							int nMaxTriangleCount;
							float fMaxDistance;
						};
						const LODSetting nLodsMaxTriangleCounts[] = { {2000, 60.f}, {500, 90.f}, {100, 120.f} };
						
						// from second lod
						for (int i = 0; pParaXMesh && i < sizeof(nLodsMaxTriangleCounts)/sizeof(LODSetting); i++)
						{
							if ((int)pParaXMesh->GetPolyCount() >= nLodsMaxTriangleCounts[i].nMaxTriangleCount)
							{
								MeshLOD lod;
								lod.m_pParaXMesh = p.ParseParaXModel((std::min)(nLodsMaxTriangleCounts[i].nMaxTriangleCount, (int)(pParaXMesh->GetPolyCount() / 2) - 4));
								lod.m_fromDepthSquared = Math::Sqr(nLodsMaxTriangleCounts[i].fMaxDistance);
								if (lod.m_pParaXMesh)
								{
									if (pMeshLODs.size() == 1)
									{
										iCur->m_fromDepthSquared = Math::Sqr(nLodsMaxTriangleCounts[0].fMaxDistance*0.5f);
									}
									pParaXMesh = lod.m_pParaXMesh;
									pMeshLODs.push_back(lod);
									iCur = pMeshLODs.end() - 1;
								}
							}
						}
					}
#endif
				}

#ifdef SUPPORT_FBX_MODEL_FILE
				else if (sExt == "fbx")
				{
					// static or animated fbx model
					FBXParser parser(iCur->m_sMeshFileName);
					iCur->m_pParaXMesh = parser.ParseParaXModel(myFile.getBuffer(), myFile.getSize());
				}
#endif
				else
				{
					CParaXSerializer serializer;
#if  defined(USE_DIRECTX_RENDERER) && !defined(_DEBUG)
					ParaXParser parser(myFile, CAsyncLoader::GetSingleton().GetFileParser());
					iCur->m_pParaXMesh = (CParaXModel*)serializer.LoadParaXMesh(myFile, parser);
#else
					iCur->m_pParaXMesh = (CParaXModel*)serializer.LoadParaXMesh(myFile);
#endif
				}
				if (iCur->m_pParaXMesh == 0)
				{
					// lod.m_pParaXMesh = new CParaXModel(ParaXHeaderDef());
					OUTPUT_LOG("warning: cannot load ParaX model file %s\n", iCur->m_sMeshFileName.c_str());
					return E_FAIL;
				}

				if (!iCur->m_pParaXMesh->IsValid())
				{
					return E_FAIL;
				}
				else
				{
					m_nTechniqueHandle = iCur->m_pParaXMesh->IsBmaxModel() ? TECH_BMAX_MODEL : TECH_CHARACTER;
				}
			}
		}
	}
	catch (...)
	{
		OUTPUT_LOG("warning: failed initialize ParaX model %s\n", m_asset->GetLocalFileName().c_str());
		return E_FAIL;
	}
	return S_OK;
}
示例#2
0
HRESULT ParaEngine::CParaXProcessor::CopyToResource()
{
	if (m_asset.get() == 0)
		return E_FAIL;
	if (m_asset->m_MeshLODs.size() == 0)
	{
		string filename = m_asset->GetLocalFileName();

		bool bLoadHeaderFromXFile = true;
		bool bSingleLOD = true;
		bool bIsXML = (CParaFile::GetFileExtension(filename) == "xml");
		string sParentDirectory = CParaFile::GetParentDirectoryFromPath(filename);


		// check in manifest
		AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(filename);
		if (pEntry)
		{
			if (pEntry->DoesFileExist())
			{
				filename = pEntry->GetLocalFileName();
			}
			else
			{
				m_pAssetFileEntry = pEntry;
				return E_PENDING;
			}
		}

		if (bIsXML)
		{
			CParaMeshXMLFile file;
			if (file.LoadFromFile(filename, sParentDirectory))
			{
				if (file.GetType() == CParaMeshXMLFile::TYPE_MESH_LOD)
				{
					int i;
					// check if all sub files are available locally.
					for (i = 0; i < file.GetSubMeshCount(); ++i)
					{
						CParaMeshXMLFile::CSubMesh* pSubLODMesh = file.GetSubMesh(i);
						AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(pSubLODMesh->m_sFileName);
						if (pEntry)
						{
							if (pEntry->DoesFileExist())
							{
								pSubLODMesh->m_sFileName = pEntry->GetLocalFileName();
							}
							else
							{
								m_pAssetFileEntry = pEntry;
								return E_PENDING;
							}
						}
					}

					if (file.m_bHasBoundingBox)
					{
					}

					for (i = 0; i < file.GetSubMeshCount(); ++i)
					{
						CParaMeshXMLFile::CSubMesh* pSubLODMesh = file.GetSubMesh(i);
						CreateMeshLODLevel(pSubLODMesh->m_fToCameraDist, pSubLODMesh->m_sFileName);
					}
					if (file.GetSubMeshCount() == 0)
					{
						OUTPUT_LOG("warning: LOD file %s does not contain any lod mesh references\n", filename.c_str());
						return E_FAIL;
					}
				}
			}
			else
			{
				OUTPUT_LOG("failed loading mesh xml file: %s\n", filename.c_str());
				return E_FAIL;
			}
		}
		else
		{
			CreateMeshLODLevel(0.f, filename);
		}
	}

	try
	{
		// preload file data to memory in the IO thread. 
		std::vector<MeshLOD> & pMeshLODs = m_MeshLODs.size() > 0 ? m_MeshLODs : m_asset->m_MeshLODs;
		std::vector<MeshLOD>::iterator iCur, iEnd = pMeshLODs.end();
		for (iCur = pMeshLODs.begin(); iCur != iEnd; ++iCur)
		{
			MeshLOD& lod = (*iCur);
			if (lod.m_pParaXMesh == 0)
			{
				CParaFile myFile(lod.m_sMeshFileName.c_str());

				if (myFile.isEof())
				{
					OUTPUT_LOG("warning: ParaX model file not found %s\n", lod.m_sMeshFileName.c_str());
					return E_FAIL;
				}

				std::string sExt = CParaFile::GetFileExtension(lod.m_sMeshFileName);
				StringHelper::make_lower(sExt);
				if (sExt == "bmax")
				{
					// block max model. 
					BMaxParser p(myFile.getBuffer(), myFile.getSize());
					lod.m_pParaXMesh = p.ParseParaXModel();
				}

#ifdef SUPPORT_FBX_MODEL_FILE
				else if (sExt == "fbx")
				{
					// static or animated fbx model
					FBXParser parser(lod.m_sMeshFileName);
					lod.m_pParaXMesh = parser.ParseParaXModel(myFile.getBuffer(), myFile.getSize());
				}
#endif
				else
				{
					CParaXSerializer serializer;
#ifdef USE_DIRECTX_RENDERER
					ParaXParser parser(myFile, CAsyncLoader::GetSingleton().GetFileParser());
					lod.m_pParaXMesh = (CParaXModel*)serializer.LoadParaXMesh(myFile, parser);
#elif defined(USE_OPENGL_RENDERER)
					lod.m_pParaXMesh = (CParaXModel*)serializer.LoadParaXMesh(myFile);
#endif
				}
				if (lod.m_pParaXMesh == 0)
				{
					// lod.m_pParaXMesh = new CParaXModel(ParaXHeaderDef());
					OUTPUT_LOG("warning: cannot load ParaX model file %s\n", lod.m_sMeshFileName.c_str());
					return E_FAIL;
				}

				if (!lod.m_pParaXMesh->IsValid())
				{
					return E_FAIL;
				}
				else
				{
					m_nTechniqueHandle = lod.m_pParaXMesh->IsBmaxModel() ? TECH_BMAX_MODEL : TECH_CHARACTER;
				}
			}
		}
	}
	catch (...)
	{
		OUTPUT_LOG("warning: failed initialize ParaX model %s\n", m_asset->GetLocalFileName().c_str());
		return E_FAIL;
	}
	return S_OK;
}