HRESULT ParaEngine::CCCSFaceLoader::Load() { if (CParaFile::DoesFileExist(m_sFileName.c_str(), false)) return S_OK; // check if all textures involved are loaded. for (int i = 0; i < CFS_TOTAL_NUM; ++i) { FaceTextureComponent& component = m_layers[i]; if (component.name.empty()) continue; AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(component.name); if (pEntry) { if (!pEntry->DoesFileExist()) { m_pAssetFileEntry = pEntry; return E_PENDING; } } } #ifdef USE_DIRECTX_RENDERER return ComposeWithGDIPlus(); #else return S_OK; #endif }
void ParaEngine::CSkinLayers::DoPaint(CPaintDevice* pd) { // DO the texture composition here CPainter painter(pd); int nSize = (int)m_layers.size(); for (int i = 0; i < nSize; ++i) { CharTextureComponent &component = m_layers[i]; const CharRegionCoords &coords = CCharCustomizeSysSetting::regions[component.region]; // load the component texture if (component.name.empty()) continue; string componentfilename = component.name; AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(componentfilename); if (pEntry) componentfilename = pEntry->GetLocalFileName(); TextureEntity* pTextureEntity = CGlobals::GetAssetManager()->LoadTexture(componentfilename, componentfilename); if (pTextureEntity) { Color color = component.GetColor(); painter.setPen(color); QRect rect(coords.xpos, coords.ypos, coords.xsize, coords.ysize); /*if (IsFlipY()) { rect.setTop(CCharCustomizeSysSetting::CharTexSize - coords.ypos - rect.height()); }*/ painter.drawTexture(rect, pTextureEntity); } } }
int CAssetManifest::CheckSyncFile(const char* filename) { AssetFileEntry* pEntry = GetFile(filename); if(pEntry) { return pEntry->CheckSyncFile() ? 1 : -1; } else return 0; }
void ParaEngine::CFaceLayers::OnTaskCompleted() { for (int i = 0; i < CFS_TOTAL_NUM; ++i) { const FaceTextureComponent& component = m_layers[i]; // load the component texture if (component.name.empty()) continue; TextureEntity* pTextureEntity = NULL; AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(component.name); if (pEntry) pTextureEntity = CGlobals::GetAssetManager()->LoadTexture(pEntry->GetLocalFileName(), pEntry->GetLocalFileName()); else pTextureEntity = CGlobals::GetAssetManager()->LoadTexture(component.name, component.name); if (pTextureEntity) { pTextureEntity->UnloadAsset(); } } }
void ParaEngine::CSkinLayers::OnTaskCompleted() { int nSize = (int)m_layers.size(); for (int i = 0; i < nSize; ++i) { CharTextureComponent &component = m_layers[i]; const CharRegionCoords &coords = CCharCustomizeSysSetting::regions[component.region]; // load the component texture if (component.name.empty()) continue; string componentfilename = component.name; AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(componentfilename); if (pEntry) componentfilename = pEntry->GetLocalFileName(); TextureEntity* pTextureEntity = CGlobals::GetAssetManager()->LoadTexture(componentfilename, componentfilename); if (pTextureEntity) { pTextureEntity->UnloadAsset(); } } }
void ParaEngine::CFaceLayers::DoPaint(CPaintDevice* pd) { // DO the texture composition here CPainter painter(pd); for (int i = 0; i<CFS_TOTAL_NUM; ++i) { const CharRegionCoords &coords = CCharCustomizeSysSetting::regions[CR_FACE_BASE + i]; const FaceTextureComponent& component = m_layers[i]; // load the component texture if (component.name.empty()) continue; string componentfilename = component.name; AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(componentfilename); if (pEntry) componentfilename = pEntry->GetLocalFileName(); // compute the transform matrix QTransform transformMatrix; // scale around the center float fScale = component.GetScaling(); if (fabs(fScale)>0.01f) { transformMatrix.scale(fScale + 1.f, fScale + 1.f); } // rotate around the center float fRotation = component.GetRotation(); if (fabs(fRotation) > 0.01f) { transformMatrix.rotateRadians(fRotation); } // translation int x, y; component.GetPosition(&x, &y); transformMatrix.translate(coords.xpos + (float)x, coords.ypos + (float)y); painter.setWorldTransform(transformMatrix, false); Color color = component.GetColor(); painter.setPen(color); TextureEntity* pTextureEntity = CGlobals::GetAssetManager()->LoadTexture(componentfilename, componentfilename); if (pTextureEntity) { QRect rect((-coords.xsize / 2), (-coords.ysize / 2), coords.xsize, coords.ysize); painter.drawTexture(rect, pTextureEntity); } // for eye and eye bow, there should be a mirrored image, around the center of the render target if (i == CFS_EYE || i == CFS_EYEBROW) { QTransform reflectMat(-1.f, 0.f, 0.f, 1.f, CCharCustomizeSysSetting::FaceTexSize - (coords.xpos + (float)x) * 2, 0.f); transformMatrix = reflectMat * transformMatrix; painter.setWorldTransform(transformMatrix, false); if (pTextureEntity) { QRect rect((-coords.xsize / 2), (-coords.ysize / 2), coords.xsize, coords.ysize); painter.drawTexture(rect, pTextureEntity); } } } }
int CParaFile::OpenAssetFile(const char* filename, bool bDownloadIfNotUpToDate, const char* relativePath) { if (relativePath != NULL) { int nRes = OpenAssetFile(filename, bDownloadIfNotUpToDate); if (nRes == 0) { // try relative path if not exist. char sNewFilename[MAX_PATH * 2]; CFileUtils::MakeFileNameFromRelativePath(sNewFilename, filename, relativePath); nRes = OpenAssetFile(sNewFilename, bDownloadIfNotUpToDate); } return nRes; } AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(filename); if (pEntry) { if (CParaFile::DoesFileExist(filename, false)) { CAsyncLoader::GetSingleton().log(string("ParaFile.OpenAssetFile using disk file:") + filename + "\n"); if (OpenFile(filename, true, relativePath)) return 1; else { OUTPUT_LOG("error: failed open disk file: %s\n", filename); } } if (pEntry->DoesFileExist()) { if (m_filename.empty()) m_filename = filename; return OpenFile(pEntry->GetLocalFileName().c_str(), true, relativePath) ? 1 : 0; } else { if (!bDownloadIfNotUpToDate) { return 0; } else { // download the file here. if (pEntry->SyncFile()) { // open the file now. if (m_filename.empty()) m_filename = filename; return OpenFile(pEntry->GetLocalFileName().c_str(), true, relativePath) ? 1 : 0; } } } } else { CAsyncLoader::GetSingleton().log(string("ParaFile.OpenAssetFile using local file:") + filename + "\n"); #ifdef PARAENGINE_MOBILE if (relativePath == NULL) { uint32 dwFound = FILE_NOT_FOUND; // check file existence, then open file will prevent file not found warnings in mobile version. if ((dwFound = CParaFile::DoesFileExist2(filename, FILE_ON_DISK | FILE_ON_ZIP_ARCHIVE | FILE_ON_SEARCH_PATH))) { return OpenFile(filename, true, relativePath, false, dwFound) ? 1 : 0; } return 0; } #endif return OpenFile(filename, true, relativePath) ? 1 : 0; } return 0; }
CAudioSource2_ptr ParaEngine::CAudioEngine2::Create(const char* sName, const char* sWavePath, bool bStream) { CAudioSource2_ptr pWave; AudioFileMap_type::iterator iter = m_audio_file_map.find(sName); if (iter!=m_audio_file_map.end()) { pWave = iter->second; if(!pWave) { pWave = new CAudioSource2(sName); iter->second = pWave; } if(pWave->m_pSource) { pWave->m_pSource->stop(); } } else { pWave = new CAudioSource2(sName); m_audio_file_map[sName] = pWave; } if(m_pAudioEngine == 0) return pWave; AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(sWavePath); if(pEntry) { if(pEntry->DoesFileExist()) { // we already downloaded the file, so load it. IParaAudioSource* pSource = NULL; #ifdef PARAENGINE_MOBILE // streaming should be disabled since it is too slow on mobile disk. OUTPUT_LOG("streaming audio file %s is disabled since it is too slow on mobile disk\n", pEntry->GetLocalFileName().c_str()); bStream = false; #endif if(bStream) { // Since local cache filename does not have file extension, however audio engine needs to have an extension in order to load from file. // so we will create a file with the proper extension in the same directory. std::string filename = pEntry->GetFullFilePath() + "." + CParaFile::GetFileExtension(sWavePath); // OUTPUT_LOG("info:streaming audio file from %s\n", filename.c_str()); if(!CParaFile::DoesFileExist(filename.c_str(), false)) { if(CParaFile::CopyFile(pEntry->GetLocalFileName().c_str(), filename.c_str(), true)) { pSource = m_pAudioEngine->create(sName, filename.c_str(), bStream); } else { OUTPUT_LOG("warning: failed to copy audio file from %s to %s\n", pEntry->GetLocalFileName().c_str(), filename.c_str()); } } else { pSource = m_pAudioEngine->create(sName, filename.c_str(), bStream); } } else { // always load from memory if no streaming is specified. ParaEngine::CParaFile file(pEntry->GetLocalFileName().c_str()); // OUTPUT_LOG("info:playing in memory audio file from %s\n", pEntry->GetLocalFileName().c_str()); if(!file.isEof()) { std::string file_extension = CParaFile::GetFileExtension(sWavePath); pSource = m_pAudioEngine->createFromMemory(sName, file.getBuffer(), file.getSize(), file_extension.c_str()); } else { OUTPUT_LOG("warning: failed to open audio file %s\n", pEntry->GetLocalFileName().c_str()); } } if(pSource) { pWave->SetSource(pSource); // if there is pending looped sound, we will play it. For non-looping sound that has just finished downloading, we will ignore it. if(pWave->m_bIsAsyncLoadingWhileLoopPlaying) { pWave->play2d(true); } } } else { CWaveFileDownloadCallBackData2 callBack(sName, sWavePath, bStream); // we shall wait for asset completion. pEntry->SyncFile_Async(callBack); } } else { #if !(defined(STATIC_PLUGIN_CAUDIOENGINE)) && !(defined(PARAENGINE_MOBILE) && defined(WIN32)) if(ParaEngine::CParaFile::DoesFileExist(sWavePath, false)) { IParaAudioSource* pSource = m_pAudioEngine->create(sName, sWavePath, bStream); if(pSource) { pWave->SetSource(pSource); } } else #endif { // currently it will unzip file each time a zipped music is played. We may first check a fixed temp location and play it from there before extracting to it. ParaEngine::CParaFile file(sWavePath); if(!file.isEof()) { #ifdef PARAENGINE_MOBILE OUTPUT_LOG("audio file opened: %s \n", sWavePath); #endif std::string file_extension = CParaFile::GetFileExtension(sWavePath); IParaAudioSource* pSource = m_pAudioEngine->createFromMemory(sWavePath, file.getBuffer(), file.getSize(), file_extension.c_str()); if(pSource) { pWave->SetSource(pSource); } } } } return pWave; }
HRESULT ParaEngine::CAudioEngine2::PlayWaveFile( const char* sWavePath, bool bLoop, bool bStream/*=false*/, int dwPlayOffset/*=0*/ ) { if(!IsValidAndEnabled() || GetGlobalVolume()<=0.f) return E_FAIL; // check if the wave file is already prepared before CAudioSource2_ptr pWave; AudioFileMap_type::iterator iter = m_audio_file_map.find(sWavePath); if (iter!=m_audio_file_map.end()) { pWave = iter->second; if(pWave && pWave->m_pSource) { if(pWave->m_pSource->isPlaying()) { // already playing, so return. #ifdef DEBUG_AUDIO OUTPUT_LOG("PlayWaveFile: %s already playing. audio pos: %d, audio time:%f, total size %d, volume %f\n", sWavePath, pWave->m_pSource->getCurrentAudioPosition(), pWave->m_pSource->getCurrentAudioTime(), pWave->m_pSource->getTotalAudioSize(), pWave->m_pSource->getVolume()); #endif return S_OK; } } else { // it usually means that the music is pending for downloading. #ifdef DEBUG_AUDIO OUTPUT_LOG("PlayWaveFile: %s pending for download\n", sWavePath); #endif return S_OK; } } else { // prepare the wave file. bool bSucceed = false; AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(sWavePath); if(pEntry) { if(pEntry->DoesFileExist()) { // we already downloaded the file, so load it. IParaAudioSource* pSource = NULL; if(bStream) { // Since local cache filename does not have file extension, however audio engine needs to have an extension in order to load from file. // so we will create a file with the proper extension in the same directory. std::string filename = pEntry->GetFullFilePath() + "." + CParaFile::GetFileExtension(sWavePath); if(!CParaFile::DoesFileExist(filename.c_str(), false)) { if(CParaFile::CopyFile(pEntry->GetLocalFileName().c_str(), filename.c_str(), false)) { pSource = m_pAudioEngine->create(sWavePath, filename.c_str(), bStream); } } else { pSource = m_pAudioEngine->create(sWavePath, filename.c_str(), bStream); } } else { // always load from memory if no streaming is specified. ParaEngine::CParaFile file(pEntry->GetLocalFileName().c_str()); if(!file.isEof()) { std::string file_extension = CParaFile::GetFileExtension(sWavePath); pSource = m_pAudioEngine->createFromMemory(sWavePath, file.getBuffer(), file.getSize(), file_extension.c_str()); } } if(pSource) { pWave = new CAudioSource2(sWavePath, pSource); m_audio_file_map[sWavePath] = pWave; bSucceed = true; } } else { // push to the queue. m_audio_file_map[sWavePath] = CAudioSource2_ptr(new CAudioSource2(sWavePath)); CWaveFilePlayCallBackData2 callBack(sWavePath, bLoop, bStream); // we shall wait for asset completion. pEntry->SyncFile_Async(callBack); } } else { #if !(defined(STATIC_PLUGIN_CAUDIOENGINE)) && !(defined(PARAENGINE_MOBILE) && defined(WIN32)) if(ParaEngine::CParaFile::DoesFileExist(sWavePath, false)) { IParaAudioSource* pSource = m_pAudioEngine->create(sWavePath, sWavePath, bStream); if(pSource) { pWave = new CAudioSource2(sWavePath, pSource); m_audio_file_map[sWavePath] = pWave; bSucceed = true; #ifdef DEBUG_AUDIO OUTPUT_LOG("PlayWaveFile: new audio %s prepared \n", sWavePath); #endif } } else #endif { // currently it will unzip file each time a zipped music is played. We may first check a fixed temp location and play it from there before extracting to it. ParaEngine::CParaFile file(sWavePath); if(!file.isEof()) { std::string file_extension = CParaFile::GetFileExtension(sWavePath); IParaAudioSource* pSource = m_pAudioEngine->createFromMemory(sWavePath, file.getBuffer(), file.getSize(), file_extension.c_str()); if(pSource) { pWave = new CAudioSource2(sWavePath, pSource); m_audio_file_map[sWavePath] = pWave; bSucceed = true; } } } } if(!bSucceed) { m_audio_file_map[sWavePath] = CAudioSource2_ptr(new CAudioSource2(sWavePath)); OUTPUT_LOG("unable to prepare wave file %s\r\n", sWavePath); return E_FAIL; } } // play the sound if(pWave) { if( ! (pWave->play2d(bLoop, false)) ) { return E_FAIL; } #ifdef DEBUG_AUDIO if(pWave->m_pSource) { OUTPUT_LOG("PlayWaveFile: play2d is called for %s. audio pos: %d, audio time:%f, total size %d, volume %f\n", sWavePath, pWave->m_pSource->getCurrentAudioPosition(), pWave->m_pSource->getCurrentAudioTime(), pWave->m_pSource->getTotalAudioSize(), pWave->m_pSource->getVolume()); } #endif } return S_OK; }
HRESULT ParaEngine::CAudioEngine2::PrepareWaveFile( CAudioSource2_ptr& pWave, const char* sWavePath, bool bStream ) { // prepare the wave file. bool bSucceed = false; if(!pWave) return E_FAIL; if(pWave->GetSource() != NULL ) { OUTPUT_LOG("warning: repeated all to already prepared wave file %s\n", sWavePath); return S_OK; } AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(sWavePath); if(pEntry) { if(pEntry->DoesFileExist()) { // we already downloaded the file, so load it. IParaAudioSource* pSource = NULL; if(bStream) { // Since local cache filename does not have file extension, however audio engine needs to have an extension in order to load from file. // so we will create a file with the proper extension in the same directory. std::string filename = pEntry->GetLocalFileName() + "."+ CParaFile::GetFileExtension(sWavePath); if(!CParaFile::DoesFileExist(filename.c_str(), false)) { if(CParaFile::CopyFile(pEntry->GetLocalFileName().c_str(), filename.c_str(), false)) { pSource = m_pAudioEngine->create(sWavePath, filename.c_str(), bStream); } } else { pSource = m_pAudioEngine->create(sWavePath, filename.c_str(), bStream); } } else { // always load from memory if no streaming is specified. ParaEngine::CParaFile file(pEntry->GetLocalFileName().c_str()); if(!file.isEof()) { std::string file_extension = CParaFile::GetFileExtension(sWavePath); pSource = m_pAudioEngine->createFromMemory(sWavePath, file.getBuffer(), file.getSize(), file_extension.c_str()); } } if(pSource) { pWave->SetSource(pSource); bSucceed = true; } } } else { #if !(defined(STATIC_PLUGIN_CAUDIOENGINE)) && !(defined(PARAENGINE_MOBILE) && defined(WIN32)) if(ParaEngine::CParaFile::DoesFileExist(sWavePath, false)) { IParaAudioSource* pSource = m_pAudioEngine->create(sWavePath, sWavePath, bStream); if(pSource) { pWave->SetSource(pSource); bSucceed = true; } } else #endif { // currently it will unzip file each time a zipped music is played. We may first check a fixed temp location and play it from there before extracting to it. ParaEngine::CParaFile file(sWavePath); if(!file.isEof()) { std::string file_extension = CParaFile::GetFileExtension(sWavePath); IParaAudioSource* pSource = m_pAudioEngine->createFromMemory(sWavePath, file.getBuffer(), file.getSize(), file_extension.c_str()); if(pSource) { pWave->SetSource(pSource); bSucceed = true; } } } } return (bSucceed) ? S_OK : E_FAIL; }
HRESULT ParaEngine::CCCSFaceLoader::ComposeWithGDIPlus() { HRESULT hr = S_OK; #ifdef USE_DIRECTX_RENDERER // DO the texture composition here CGDIEngine* pEngine = CAsyncLoader::GetSingleton().GetGDIEngine(); if (pEngine == NULL) return E_FAIL; pEngine->SetRenderTarget(pEngine->CreateGetRenderTargetBySize(CCharCustomizeSysSetting::FaceTexSize)); pEngine->Begin(); for (int i = 0; i<CFS_TOTAL_NUM; ++i) { const CharRegionCoords &coords = CCharCustomizeSysSetting::regions[CR_FACE_BASE + i]; const FaceTextureComponent& component = m_layers[i]; // load the component texture if (component.name.empty()) continue; string componentfilename = component.name; AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(componentfilename); if (pEntry) componentfilename = pEntry->GetLocalFileName(); // compute the transform matrix Gdiplus::Matrix transformMatrix; // scale around the center float fScale = component.GetScaling(); if (fabs(fScale)>0.01f) { transformMatrix.Scale(fScale + 1.f, fScale + 1.f); } // rotate around the center float fRotation = component.GetRotation(); if (fabs(fRotation) > 0.01f) { transformMatrix.Rotate(fRotation); } // translation int x, y; component.GetPosition(&x, &y); transformMatrix.Translate(coords.xpos + (float)x, coords.ypos + (float)y); pEngine->SetTransform(&transformMatrix); Color color = component.GetColor(); pEngine->DrawImage(pEngine->LoadTexture(componentfilename, component.name), (float)(-coords.xsize / 2), (float)(-coords.ysize / 2), (float)coords.xsize, (float)coords.ysize, color); // for eye and eye bow, there should be a mirrored image, around the center of the render target if (i == CFS_EYE || i == CFS_EYEBROW) { Gdiplus::Matrix reflectMat(-1.f, 0.f, 0.f, 1.f, CCharCustomizeSysSetting::FaceTexSize - (coords.xpos + (float)x) * 2, 0.f); transformMatrix.Multiply(&reflectMat); pEngine->SetTransform(&transformMatrix); pEngine->DrawImage(pEngine->LoadTexture(componentfilename, component.name), (float)(-coords.xsize / 2), (float)(-coords.ysize / 2), (float)coords.xsize, (float)coords.ysize); } } CParaFile::CreateDirectory(m_sFileName.c_str()); hr = (pEngine->SaveRenderTarget(m_sFileName, CCharCustomizeSysSetting::FaceTexSize, CCharCustomizeSysSetting::FaceTexSize, false, 0)) ? S_OK : E_FAIL; pEngine->End(); #endif return hr; }
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; }
void CAssetManifest::AddEntry(const char* filename) { if(filename==0) return; string sFilename = filename; string fileKey; string md5; string filesize; if (ParseAssetEntryStr(sFilename, fileKey, md5, filesize)) { string file_extension; // to lower case and replace "\\" with "/" MakeValidFileName(fileKey); bool bIsZipfile = false; int nLen = (int)(fileKey.size()); if(nLen > 2 && fileKey[nLen-2] == '.') { if( fileKey[nLen-1] == 'p') { // non-compressed file fileKey.resize(nLen-2); } else if( fileKey[nLen-1] == 'z') { // compressed file bIsZipfile = true; fileKey.resize(nLen-2); } } int nFileSize = atoi(filesize.c_str()); if(nFileSize == 0) { // ignore file whose size is 0. return; } Asset_Manifest_Map_Type::iterator iter = m_files.find(fileKey); if(iter != m_files.end()) { // replace old one. SAFE_DELETE(iter->second); } // extract file extension and parent directory for(int i=(int)fileKey.size()-1;i>=0;--i) { char ch = fileKey[i]; if(ch=='.' && file_extension.empty()) { int nCount = (int)fileKey.size()-(i+1); if(nCount>0) file_extension = fileKey.substr(i+1,nCount); } else if(ch=='/') { // also add parent directory to list, so that DoesAssetFileExist() will return true for directory entries as well. string sParentDir = fileKey.substr(0, i); iter = m_files.find(sParentDir); if(iter == m_files.end()) { AssetFileEntry* pEntry = new AssetFileEntry(); pEntry->m_url = sParentDir; pEntry->m_bIsZipFile = false; m_files[sParentDir] = pEntry; } break; } } AssetFileEntry* pEntry = new AssetFileEntry(); pEntry->m_url = filename; pEntry->m_localFileName.reserve(pEntry->m_localFileName.size()+63); pEntry->m_localFileName += "temp/cache/a/"; pEntry->m_localFileName[11] = md5[0]; pEntry->m_localFileName += md5; pEntry->m_localFileName += filesize; pEntry->m_bIsZipFile = bIsZipfile; pEntry->m_nFileSize = nFileSize; pEntry->SetFileType(file_extension); // note: this function must be called after file size is set. m_files[fileKey] = pEntry; // OUTPUT_LOG("asset manifest: %s, %s, ziped:%d\n", pEntry->m_url.c_str(), pEntry->m_localFileName.c_str(), pEntry->m_bIsZipFile ? 1 : 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; }