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; }
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; }