#define NO_GDI #include "stdafx.h" #undef NO_GDI #include "Cry3dEngineBase.h" //#include #include "dds.h" #include "LMSerializationManager2.h" #include #include "IEntityRenderState.h" #include // STL find #include // STL set<> #include #include "ObjMan.h" #include "Brush.h" #define LEVELLM_PAK_NAME "LevelLM.pak" CLMSerializationManager2::CLMSerializationManager2(){} CLMSerializationManager2::~CLMSerializationManager2() { for (std::vector::iterator itLMData=m_vLightPatches.begin(); itLMData!=m_vLightPatches.end(); itLMData++) delete (*itLMData); } void CLMSerializationManager2::AddRawLMData( const DWORD indwWidth, const DWORD indwHeight, const std::vector& _vGLM_IDs_UsingPatch, BYTE *_pColorLerp4, BYTE *_pHDRColorLerp4, BYTE *_pDomDirection3, BYTE *_pOccl2) { std::vector::iterator itLMData; // for all stored lightmaps for(itLMData=m_vLightPatches.begin(); itLMData!=m_vLightPatches.end();) { std::vector::const_iterator itID; RawLMData *pCurRawLMData = *itLMData; // for all the given new object ids for (itID=_vGLM_IDs_UsingPatch.begin(); itID!=_vGLM_IDs_UsingPatch.end(); itID++) { int id=*itID; std::vector::iterator itRemove=std::find(pCurRawLMData->vGLM_IDs_UsingPatch.begin(),pCurRawLMData->vGLM_IDs_UsingPatch.end(),id); if(itRemove!=pCurRawLMData->vGLM_IDs_UsingPatch.end()) pCurRawLMData->vGLM_IDs_UsingPatch.erase(itRemove); } // if the lightmap is no longer used by any object - remove it if(pCurRawLMData->vGLM_IDs_UsingPatch.empty()) { delete pCurRawLMData; pCurRawLMData=0; itLMData=m_vLightPatches.erase(itLMData); } else ++itLMData; } RawLMData* pRawLM = new RawLMData(indwWidth, indwHeight,_vGLM_IDs_UsingPatch); pRawLM->initFromBMP (RawLMData::TEX_COLOR, _pColorLerp4); pRawLM->initFromBMP (RawLMData::TEX_DOMDIR, _pDomDirection3); if(_pOccl2 != 0) { pRawLM->initFromBMP (RawLMData::TEX_OCCL, _pOccl2); pRawLM->m_bUseOcclMaps = true; } else pRawLM->m_bUseOcclMaps = false; if(_pHDRColorLerp4 != 0) { pRawLM->initFromBMP (RawLMData::TEX_HDR, _pHDRColorLerp4); pRawLM->m_bUseHDRMaps = true; } else pRawLM->m_bUseHDRMaps = false; m_vLightPatches.push_back(pRawLM); } void CLMSerializationManager2::AddTexCoordData(const std::vector& vTexCoords, int iGLM_ID_UsingTexCoord, const DWORD indwHashValue, const std::vector >& rOcclIDs) { m_vTexCoords[iGLM_ID_UsingTexCoord] = RawTexCoordData(vTexCoords,indwHashValue, rOcclIDs); } struct AutoFileCloser: Cry3DEngineBase { AutoFileCloser(FILE*pFile):m_pFile(pFile){} ~AutoFileCloser(){if (m_pFile)GetPak()->FClose(m_pFile);} protected: FILE* m_pFile; }; #ifdef WIN64 #pragma warning( push ) //AMD Port #pragma warning( disable : 4267 ) #endif bool CLMSerializationManager2::_Load( const char *pszFileName, std::vector *inpIGLMs, const bool cbLoadTextures) { // --------------------------------------------------------------------------------------------- // Reconstruct lightmap data from pszFileName // --------------------------------------------------------------------------------------------- GetSystem()->GetILog()->UpdateLoadingScreen("\003Loading lightmaps ..."); string strDirName = CryStringUtils::GetParentDirectory(pszFileName); // make sure the pak file in which this LM data resides is opened GetPak()->OpenPack ((strDirName + "\\" LEVELLM_PAK_NAME).c_str()); FileHeader sHeader; size_t iNumItemsRead; std::map mapLMData; // only used if inpIGLMs!=0 if(inpIGLMs) { if(inpIGLMs->empty()) { GetSystem()->GetILog()->Log("No GLMs to load lightmaps for"); return false; } } else { assert(m_vLightPatches.empty()); assert(m_vTexCoords.empty()); } // Open file FILE* hFile = GetPak()->FOpen(pszFileName, "rb"); if (hFile == NULL) { GetSystem()->GetILog()->Log("Could not load lightmap file"); return false; } AutoFileCloser _AutoClose (hFile); // Read header iNumItemsRead = GetPak()->FRead(&sHeader, sizeof(FileHeader), 1, hFile); // Read LM texture data for (UINT iCurLMTexData = 0; iCurLMTexData < sHeader.iNumLM_Pairs; ++iCurLMTexData) { LMHeader LM; // width, height and the number of UVs if (1 != GetPak()->FRead(&LM, sizeof(LM), 1, hFile)) { Warning (0, pszFileName, "Cannot read LM data header #%d", iCurLMTexData); GetSystem()->GetILog()->Log("Cannot read Lightmap data header "); return false; } std::vector vGLM_IDs_UsingPatch; // objects that use this lightmap texture vGLM_IDs_UsingPatch.resize (LM.numGLMs); // Read IDs of GLMs which use this texture pair if (1 != GetPak()->FRead(&vGLM_IDs_UsingPatch[0], sizeof(int)*LM.numGLMs, 1, hFile)) { Warning (0, pszFileName, "Cannot read LM data #%d", iCurLMTexData); GetSystem()->GetILog()->Log("Cannot read Lightmap data"); return false; } std::vectorvDomLightDir, vColorMap; if(inpIGLMs) { // Create lightmap RenderLMData_AutoPtr pNewLM = sHeader.iVersion == 2? CreateLightmap(strDirName, iCurLMTexData,LM.iWidth, LM.iHeight, false/*don't load occl maps*/) : CreateLightmap(strDirName, iCurLMTexData,LM.iWidth, LM.iHeight, true/*load occl maps*/); if (!pNewLM) { GetSystem()->GetILog()->Log("CreateLightmap has failed"); return false; } // Instance is assigned later when we get the texture coordinates. Store a // reference so we can later safely release each element for (std::vector::iterator itID=vGLM_IDs_UsingPatch.begin(); itID!=vGLM_IDs_UsingPatch.end(); itID++) { // Shouldn't happen, probably need to fix something if. Might be wrong LM data, just // delete the file or ignore the assert assert (mapLMData.find(*itID) == mapLMData.end()); mapLMData[*itID] = pNewLM; } } else { RawLMData* pRawLM = new RawLMData(LM.iWidth,LM.iHeight,vGLM_IDs_UsingPatch); char szPostfix[8]; if(cbLoadTextures) { sprintf(szPostfix, "%d.dds", iCurLMTexData); pRawLM->initFromDDS(RawLMData::TEX_COLOR, GetPak(), strDirName + "\\c" + szPostfix); pRawLM->initFromDDS(RawLMData::TEX_DOMDIR, GetPak(), strDirName + "\\d" + szPostfix); if(sHeader.iVersion > 2)//load occlusion maps too { pRawLM->initFromDDS(RawLMData::TEX_OCCL, GetPak(), strDirName + "\\o" + szPostfix); pRawLM->initFromDDS(RawLMData::TEX_HDR, GetPak(), strDirName + "\\r" + szPostfix); } } m_vLightPatches.push_back(pRawLM); } } // Read texture coordinate data for (UINT iNumTexCoordSets=0; iNumTexCoordSets= 3) pUVh = new UVSetHeader3(); else pUVh = new UVSetHeader();//old format assert(pUVh); std::auto_ptr uvh(pUVh); // Read position of GLM which uses this texture coordinate set if (1 != GetPak()->FRead(pUVh, (sHeader.iVersion>=3)?sizeof(UVSetHeader3):sizeof(UVSetHeader), 1, hFile)) { GetSystem()->GetILog()->Log("Could not read texture coordinates for lightmaps"); return false; } std::vector vTexCoords; vTexCoords.resize(pUVh->numUVs); if (1 != GetPak()->FRead(&vTexCoords[0], sizeof(TexCoord2Comp)*pUVh->numUVs, 1, hFile)) { GetSystem()->GetILog()->Log("Could not read texture coordinates for lightmaps"); return false; } #ifdef _DEBUG for (UINT iCurTexCrd=0; iCurTexCrd= 0.0f && vTexCoords[iCurTexCrd].s <= 1.0f && vTexCoords[iCurTexCrd].t >= 0.0f && vTexCoords[iCurTexCrd].t <= 1.0f ) continue; Warning(0, pszFileName, "CLMSerializationManager2::_Load: Lightmap texture coordinates out of range"); break; } #endif // Hand out data/references to the GLMs if(inpIGLMs) { std::vector::iterator itGLM; for (itGLM=inpIGLMs->begin(); itGLM!=inpIGLMs->end(); ++itGLM) { IEntityRender *pICurGLM = (* itGLM); // Correct GLM for this texture coordinate set ? if ( pICurGLM->GetEditorObjectId() == pUVh->nIdGLM && pICurGLM->GetEntityRS() ) { std::map::iterator itRenderLMData = mapLMData.find(pUVh->nIdGLM); if (itRenderLMData == mapLMData.end()) { // We shouldn't have a texture coordinate set for a GLM that has no matching LM object assert(itRenderLMData != mapLMData.end()); break; } // Copy texture coordinates and hand out a reference to the lightmap object if(sHeader.iVersion >= 3 && (strcmp(pICurGLM->GetEntityClassName(), "Brush") == 0)) { const UVSetHeader3 *puvh = static_cast(pUVh); //create vector with light ids std::vector > vIDs; vIDs.resize(puvh->ucOcclCount); for(int i=0; iucOcclCount; ++i) { vIDs[i].first = puvh->OcclIds[2*i]; vIDs[i].second = puvh->OcclIds[2*i+1]; } CBrush *pBrush = reinterpret_cast(pICurGLM);//safe due to GetEntityClassName pBrush->SetLightmap (itRenderLMData->second, (float *) &vTexCoords[0], vTexCoords.size(), puvh->ucOcclCount, vIDs); } else pICurGLM->SetLightmap (itRenderLMData->second, (float *) &vTexCoords[0], vTexCoords.size()); // Texture coordinates are per-instance break; } } } else // !inpIGLMs { m_vTexCoords[pUVh->nIdGLM] = RawTexCoordData(vTexCoords, pUVh->nHashGLM); } } GetSystem()->GetILog()->UpdateLoadingScreenPlus(" %d elements loaded", mapLMData.size()); GetSystem()->GetILog()->Log("Finished loading lightmaps ..."); return true; } bool CLMSerializationManager2::Load(const char *pszFileName, const bool cbLoadTextures) { return(_Load(pszFileName, 0, cbLoadTextures)); } bool CLMSerializationManager2::ApplyLightmapfile(const char *pszFileName, std::vector& vIGLMs ) { return(_Load(pszFileName,&vIGLMs)); } ////////////////////////////////////////////////////////////////////////// uint8* MemBufferCounter=0; int m_numMips=0; HRESULT SaveCompessedMipmapLevel( void * data, int miplevel, DWORD size, int width, int height, void * user_data ) { assert( MemBufferCounter ); uint8* src=(uint8*)data; for (uint32 i=0; i(pszFilePath); const char* pFileName = pszFilePath + (strDirName.empty()?0:strDirName.length()+1); string strPakName = strDirName + "\\" LEVELLM_PAK_NAME; GetPak()->ClosePack(strPakName.c_str()); // make sure the pak file in which this LM data resides is opened SetFileAttributes(strPakName.c_str(), FILE_ATTRIBUTE_NORMAL); ICryArchive_AutoPtr pPak = GetPak()->OpenArchive (strPakName.c_str(), ICryArchive::FLAGS_RELATIVE_PATHS_ONLY); if (!pPak) return NSAVE_RESULT::EPAK_FILE_OPEN_FAIL; unsigned int uiStartIndex = 0; if(cbAppend) { //seek to the right file for(;;) { char fileName[10]; //create filename sprintf(fileName, "x%d.dds", uiStartIndex); if(pPak->FindFile(fileName) == NULL) break; uiStartIndex++; } } FileHeader sHeader; std::map::iterator itTexCrdData; RawLMData *pCurRawLMData = NULL; RawTexCoordData *pCurRawTexCrdData = NULL; CTempFile fMem; // Write header sHeader.iNumLM_Pairs = m_vLightPatches.size(); sHeader.iNumTexCoordSets = m_vTexCoords.size(); fMem.Write(sHeader); // Write LM texture data for (UINT iCurLMTexData = 0; iCurLMTexData < m_vLightPatches.size(); ++iCurLMTexData) { pCurRawLMData = m_vLightPatches[iCurLMTexData]; LMHeader LM; LM.iHeight = pCurRawLMData->m_dwHeight; LM.iWidth = pCurRawLMData->m_dwWidth; LM.numGLMs = pCurRawLMData->vGLM_IDs_UsingPatch.size(); fMem.Write(LM); fMem.Write(&pCurRawLMData->vGLM_IDs_UsingPatch[0], LM.numGLMs); if(iCurLMTexData >= uiStartIndex) { uint32 size = pCurRawLMData->m_ColorLerp4.GetSize(); uint8* pSr0 = (uint8*)pCurRawLMData->m_ColorLerp4.GetData(); uint8* pSr1 = (uint8*)pCurRawLMData->m_DomDirection3.GetData(); DDS_HEADER* pDDS=(DDS_HEADER*)(pSr0+4); uint32 width = pDDS->dwWidth; uint32 height = pDDS->dwHeight; char szName[8]; sprintf(szName, "x%d.dds", iCurLMTexData/* + uiStartIndex*/); DDS_HEADER ddsh; if (0) {//save uncompressed version szName[0] = 'c'; pPak->UpdateFile (szName, pCurRawLMData->m_ColorLerp4.GetData(), pCurRawLMData->m_ColorLerp4.GetSize(), ICryArchive::METHOD_COMPRESS, ICryArchive::LEVEL_BEST); } else { //------------------------------------------------------------------------------- //---- create DXT3-image for color-map ------------------------------------------ //------------------------------------------------------------------------------- uint8* pColorMaps32 = (uint8*)pCurRawLMData->m_ColorLerp4.GetData();; uint8* pColorDXT3=(uint8*)malloc(size); MemBufferCounter = pColorDXT3; m_numMips=0; memset( (void*)(&ddsh), 0, sizeof(ddsh) ); *MemBufferCounter='D'; MemBufferCounter++; *MemBufferCounter='D'; MemBufferCounter++; *MemBufferCounter='S'; MemBufferCounter++; *MemBufferCounter=' '; MemBufferCounter++; ddsh.dwSize = sizeof(DDS_HEADER); ddsh.dwWidth = width; ddsh.dwHeight = height; ddsh.dwMipMapCount = 0; ddsh.ddspf = DDSPF_DXT3; ddsh.dwHeaderFlags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP; ddsh.dwSurfaceFlags = DDS_SURFACE_FLAGS_TEXTURE | DDS_SURFACE_FLAGS_MIPMAP; uint8* hsrcDXT3=(uint8*)(&ddsh); for (uint32 i=0; iGetIRenderer()->DXTCompress( &pColorMaps32[0x80], width, height, eTF_DXT3, //DXT-format false, //use hardware 0, //mipmaps on/off 4, //bytes per pixel SaveCompessedMipmapLevel //callback )) return NSAVE_RESULT::EDXT_COMPRESS_FAIL; DDS_HEADER* pDXT3=(DDS_HEADER*)(pColorDXT3+4); pDXT3->dwMipMapCount = m_numMips; if (m_numMips==1) pDXT3->dwMipMapCount = 0; szName[0] = 'c'; uint32 dxt3size=MemBufferCounter-pColorDXT3; pPak->UpdateFile (szName, pColorDXT3, dxt3size, ICryArchive::METHOD_COMPRESS, ICryArchive::LEVEL_BEST); szName[0] = 'h'; pPak->UpdateFile (szName, pCurRawLMData->m_ColorLerp4.GetData(), pCurRawLMData->m_ColorLerp4.GetSize(), ICryArchive::METHOD_COMPRESS, ICryArchive::LEVEL_BEST); free(pColorDXT3); } //------------------------------------------------------------------------------------------- szName[0] = 'd'; pPak->UpdateFile (szName, pCurRawLMData->m_DomDirection3.GetData(), pCurRawLMData->m_DomDirection3.GetSize(), ICryArchive::METHOD_COMPRESS, ICryArchive::LEVEL_BEST); if(pCurRawLMData->m_bUseOcclMaps) { szName[0] = 'o'; pPak->UpdateFile (szName, pCurRawLMData->m_Occl2.GetData(), pCurRawLMData->m_Occl2.GetSize(), ICryArchive::METHOD_COMPRESS, ICryArchive::LEVEL_BEST); } if(pCurRawLMData->m_bUseHDRMaps) { szName[0] = 'r'; pPak->UpdateFile (szName, pCurRawLMData->m_HDRColorLerp4.GetData(), pCurRawLMData->m_HDRColorLerp4.GetSize(), ICryArchive::METHOD_COMPRESS, ICryArchive::LEVEL_BEST); } uint8* pSimpleLightmaps32 = (uint8*)malloc(size); //copy headder for (uint32 i=0; i<0x80; i++) { pSimpleLightmaps32[i] = pSr0[i]; } //create simple lightmap (RGBA) for (uint32 i=0x80; iGetIRenderer()->DXTCompress( &pSimpleLightmaps32[0x80], width, height, eTF_DXT5, //DXT-format false, //use hardware 0, //mipmaps on/off 4, //bytes per pixel SaveCompessedMipmapLevel //callback )) return NSAVE_RESULT::EDXT_COMPRESS_FAIL; #else if(!GetSystem()->GetIRenderer()->DXTCompress( &pSimpleLightmaps32[0x80], width, height, eTF_DXT1, //DXT-format false, //use hardware 0, //mipmaps on/off 4, //bytes per pixel SaveCompessedMipmapLevel //callback )) return NSAVE_RESULT::EDXT_COMPRESS_FAIL; #endif DDS_HEADER* pDXT1=(DDS_HEADER*)(pSimpleLightmapsDXT1+4); pDXT1->dwMipMapCount = m_numMips; if (m_numMips==1) pDXT1->dwMipMapCount = 0; uint32 dxtsize=MemBufferCounter-pSimpleLightmapsDXT1; szName[0] = 'x'; pPak->UpdateFile (szName, pSimpleLightmapsDXT1, dxtsize, ICryArchive::METHOD_COMPRESS, ICryArchive::LEVEL_BEST); free(pSimpleLightmapsDXT1); free(pSimpleLightmaps32); } } // Write texture coordinate data for (itTexCrdData=m_vTexCoords.begin(); itTexCrdData!=m_vTexCoords.end(); itTexCrdData++) { UVSetHeader3 uvh; pCurRawTexCrdData = &((*itTexCrdData).second); uvh.nIdGLM = (*itTexCrdData).first; uvh.nHashGLM = pCurRawTexCrdData->m_dwHashValue; uvh.numUVs = pCurRawTexCrdData->vTexCoords.size(); uvh.ucOcclCount = pCurRawTexCrdData->vOcclIDs.size(); for(int i=0; ivOcclIDs[i].first;//real entity id uvh.OcclIds[2*i+1] = pCurRawTexCrdData->vOcclIDs[i].second;//light index in statlights } fMem.Write (uvh); fMem.Write(&pCurRawTexCrdData->vTexCoords[0], uvh.numUVs); } if(0 == pPak->UpdateFile(pFileName, fMem.GetData(), fMem.GetSize())) return NSAVE_RESULT::ESUCCESS; else return NSAVE_RESULT::EPAK_FILE_UPDATE_FAIL; } #ifdef WIN64 #pragma warning( pop ) //AMD Port #endif DWORD CLMSerializationManager2::GetHashValue( const int iniGLM_ID_UsingTexCoord ) const { std::map::const_iterator itTexCrdData; for (itTexCrdData=m_vTexCoords.begin(); itTexCrdData!=m_vTexCoords.end(); itTexCrdData++) { int iGLM_ID_UsingTexCoord=(*itTexCrdData).first; if(iGLM_ID_UsingTexCoord==iniGLM_ID_UsingTexCoord) { const RawTexCoordData &rCurRawTexCrdData = (*itTexCrdData).second; return(rCurRawTexCrdData.m_dwHashValue); } } return(0x12341234); // object not found } RenderLMData * CLMSerializationManager2::CreateLightmap(const string& strDirPath, int nItem, UINT iWidth, UINT iHeight, const bool cbLoadHDRMaps, const bool cbLoadOcclMaps) { // --------------------------------------------------------------------------------------------- // Create a DOT3 Lightmap object // --------------------------------------------------------------------------------------------- IRenderer *pIRenderer = GetSystem()->GetIRenderer(); int iColorLerpTex = 0, iHDRColorLerpTex = 0, iDomDirectionTex = 0, iOcclTex = 0; int nGPU = pIRenderer->GetFeatures() & RFT_HW_MASK; char szPostfix[8]; sprintf(szPostfix, "%d.dds", nItem); //--------------------------------------------------------------------------------------------------- //---- load precalculated SimpleLightmaps ----------------------------------------------------- //--------------------------------------------------------------------------------------------------- if (GetCVars()->e_light_maps_quality==0 || nGPU == RFT_HW_GF2) { ITexPic *tp = pIRenderer->EF_LoadTexture((strDirPath + "\\x" + szPostfix).c_str(), FT_LM, FT2_NOANISO, eTT_Base); iColorLerpTex = tp->GetTextureID(); return new RenderLMData(pIRenderer, iColorLerpTex, iHDRColorLerpTex, 0); } else if (GetCVars()->e_light_maps_quality==1) { //load lightsmaps in DXT3-format iColorLerpTex = pIRenderer->EF_LoadTexture((strDirPath + "\\c" + szPostfix).c_str(), FT_LM | FT_CLAMP, FT2_NOANISO, eTT_Base)->GetTextureID(); iDomDirectionTex = pIRenderer->EF_LoadTexture((strDirPath + "\\d" + szPostfix).c_str(), FT_LM | FT_CLAMP, FT2_NOANISO, eTT_Base)->GetTextureID(); } else if (GetCVars()->e_light_maps_quality==2) { //load lightmaps with high quality ITexPic *tp = pIRenderer->EF_LoadTexture((strDirPath + "\\h" + szPostfix).c_str(), FT_LM | FT_CLAMP, FT2_NOANISO, eTT_Base); if (tp && tp->IsTextureLoaded()) iColorLerpTex = tp->GetTextureID(); else { SAFE_RELEASE(tp); iColorLerpTex = pIRenderer->EF_LoadTexture((strDirPath + "\\c" + szPostfix).c_str(), FT_LM | FT_CLAMP, FT2_NOANISO, eTT_Base)->GetTextureID(); } iDomDirectionTex = pIRenderer->EF_LoadTexture((strDirPath + "\\d" + szPostfix).c_str(), FT_LM | FT_CLAMP, FT2_NOANISO, eTT_Base)->GetTextureID(); if(cbLoadOcclMaps) { iOcclTex = pIRenderer->EF_LoadTexture((strDirPath + "\\o" + szPostfix).c_str(), FT_LM | FT_CLAMP, FT2_NOANISO, eTT_Base)->GetTextureID(); } if ((pIRenderer->GetFeatures() & RFT_HW_HDR) && cbLoadHDRMaps) { ITexPic *tp = pIRenderer->EF_LoadTexture((strDirPath + "\\r" + szPostfix).c_str(), FT_LM | FT_CLAMP, FT2_NOANISO, eTT_Base); if (tp && tp->IsTextureLoaded()) iHDRColorLerpTex = tp->GetTextureID(); else SAFE_RELEASE(tp); } } return new RenderLMData(pIRenderer, iColorLerpTex, iHDRColorLerpTex, iDomDirectionTex, iOcclTex); } //---------------------------------------------------------------------------------------------------------------------------------------------------------- RenderLMData * CLMSerializationManager2::CreateLightmap(const char *pszFileName, int nItem, UINT iWidth, UINT iHeight, BYTE *pColorLerp4, BYTE *pHDRColorLerp, BYTE *pDomDirection3, BYTE *pOccl2) { // Create a DOT3 Lightmap object IRenderer *pIRenderer = GetSystem()->GetIRenderer(); int iColorLerpTex = 0, iHDRColorLerpTex = 0, iDomDirectionTex = 0, iOcclTex = 0; assert(!IsBadReadPtr(pColorLerp4, sizeof(BYTE) * 4 * iWidth * iHeight)); #ifdef USE_DOT3_ALPHA assert(!IsBadReadPtr(pDomDirection3, sizeof(BYTE) * 4 * iWidth * iHeight)); #else assert(!IsBadReadPtr(pDomDirection3, sizeof(BYTE) * 3 * iWidth * iHeight)); #endif if(pOccl2) assert(!IsBadReadPtr(pOccl2, sizeof(BYTE) * 2 * iWidth * iHeight)); if(pHDRColorLerp) assert(!IsBadReadPtr(pHDRColorLerp, sizeof(BYTE) * 4 * iWidth * iHeight)); char szName[128]; if (pszFileName) { sprintf(szName, "$DOT3LM%d$%s", nItem, pszFileName); iColorLerpTex = pIRenderer->DownLoadToVideoMemory(pColorLerp4, iWidth, iHeight, eTF_RGBA, eTF_RGBA, 0, false, FILTER_BILINEAR, 0, szName); } else iColorLerpTex = pIRenderer->DownLoadToVideoMemory(pColorLerp4, iWidth, iHeight, eTF_RGBA, eTF_RGBA, 0, false, FILTER_BILINEAR, 0, NULL); assert(iColorLerpTex != 0); #ifndef USE_DOT3_ALPHA std::vector vRGBAData; vRGBAData.resize(iWidth * iHeight * 4); for (UINT i=0; iDownLoadToVideoMemory(&vRGBAData[0], iWidth, iHeight, eTF_RGBA, eTF_RGBA, 0, false, FILTER_BILINEAR, 0, szName); } else iDomDirectionTex = pIRenderer->DownLoadToVideoMemory(&vRGBAData[0], iWidth, iHeight, eTF_RGBA, eTF_RGBA, 0, false, FILTER_BILINEAR, 0, NULL); #else if (pszFileName) { sprintf(szName, "$DOT3LMDir%d$%s", nItem, pszFileName); iDomDirectionTex = pIRenderer->DownLoadToVideoMemory(pDomDirection3, iWidth, iHeight, eTF_RGBA, eTF_RGBA, 0, false, FILTER_BILINEAR, 0, szName); } else iDomDirectionTex = pIRenderer->DownLoadToVideoMemory(pDomDirection3, iWidth, iHeight, eTF_RGBA, eTF_RGBA, 0, false, FILTER_BILINEAR, 0, NULL); #endif assert(iDomDirectionTex != 0); int nGPU = pIRenderer->GetFeatures() & RFT_HW_MASK; bool bLow = (nGPU == RFT_HW_GF2); if(!bLow && pOccl2 != 0 && (GetCVars()->e_light_maps_quality==2)) { if (pszFileName) { sprintf(szName, "$DOT3LMOccl%d$%s", nItem, pszFileName); iOcclTex = pIRenderer->DownLoadToVideoMemory(pOccl2, iWidth, iHeight, eTF_4444, eTF_4444, 0, false, FILTER_BILINEAR, 0, szName); } else iOcclTex = pIRenderer->DownLoadToVideoMemory(pOccl2, iWidth, iHeight, eTF_4444, eTF_4444, 0, false, FILTER_BILINEAR, 0, NULL); } if(!bLow && pHDRColorLerp != 0 && (GetCVars()->e_light_maps_quality==2) && (pIRenderer->GetFeatures() & RFT_HW_HDR)) { if (pszFileName) { sprintf(szName, "$DOT3LMHDR%d$%s", nItem, pszFileName); iHDRColorLerpTex = pIRenderer->DownLoadToVideoMemory(pHDRColorLerp, iWidth, iHeight, eTF_RGBA, eTF_RGBA, 0, false, FILTER_BILINEAR, 0, szName); } else iHDRColorLerpTex = pIRenderer->DownLoadToVideoMemory(pHDRColorLerp, iWidth, iHeight, eTF_RGBA, eTF_RGBA, 0, false, FILTER_BILINEAR, 0, NULL); } if (GetCVars()->e_light_maps_quality==0 || bLow) { ITexPic *pColorLerpTex = pIRenderer->EF_GetTextureByID(iColorLerpTex); byte *pDataLerpTex = pColorLerpTex->GetData32(); ITexPic *pDomDirectionTex = pIRenderer->EF_GetTextureByID(iDomDirectionTex); byte *pDataDirectionTex = pDomDirectionTex->GetData32(); int Width = pColorLerpTex->GetWidth(); int Height = pColorLerpTex->GetHeight(); assert(Width == pDomDirectionTex->GetWidth() && Height == pDomDirectionTex->GetHeight()); byte *pDst = new byte[Width*Height*4]; for (int i=0; iRelease(); pDomDirectionTex->Release(); if (pszFileName) { char szCacheName[512]; sprintf(szCacheName, "$LM%d$%s", nItem, pszFileName); iColorLerpTex = pIRenderer->DownLoadToVideoMemory(pDst, Width, Height, eTF_8888, eTF_8888, 0, false, FILTER_BILINEAR, 0, szCacheName); } else iColorLerpTex = pIRenderer->DownLoadToVideoMemory(pDst, Width, Height, eTF_8888, eTF_8888, 0, false, FILTER_BILINEAR, 0, NULL); iDomDirectionTex = 0; } return new RenderLMData(pIRenderer, iColorLerpTex, iHDRColorLerpTex, iDomDirectionTex, iOcclTex); } typedef LMStatLightFileHeader LightFileHeader; bool CLMSerializationManager2::ExportDLights(const char *pszFilePath, const CDLight **ppLights, UINT iNumLights, bool bNewZip) const { // --------------------------------------------------------------------------------------------- // Serialize dynamic lights into a file // --------------------------------------------------------------------------------------------- string strDirName = CryStringUtils::GetParentDirectory(pszFilePath); const char* pFileName = pszFilePath + (strDirName.empty()?0:strDirName.length()+1); string strPakName = strDirName + "\\" LEVELLM_PAK_NAME; GetPak()->ClosePack(strPakName.c_str()); // make sure the pak file in which this LM data resides is opened SetFileAttributes(strPakName.c_str(), FILE_ATTRIBUTE_NORMAL); if (!bNewZip) GetPak()->ClosePack( strPakName.c_str() ); ICryArchive_AutoPtr pPak = GetPak()->OpenArchive (strPakName.c_str(), ICryArchive::FLAGS_RELATIVE_PATHS_ONLY|(bNewZip?ICryArchive::FLAGS_CREATE_NEW:0)); if (!pPak) return false; LightFileHeader sHeader; UINT iCurLight; CTempFile fMem; if (iNumLights == 0) { pPak->RemoveFile (pFileName); return true; } assert(!IsBadReadPtr(ppLights, sizeof(CDLight *) * iNumLights)); sHeader.iNumDLights = iNumLights; fMem.Write (sHeader); for (iCurLight=0; iCurLightm_pLightImage ? ppLights[iCurLight]->m_pLightImage->GetFlags2() : 0; fMem.Write (nFlags2); ITexPic* pLightImg = ppLights[iCurLight]->m_pLightImage; WriteString(pLightImg? pLightImg->GetName() : "" , fMem); IShader* pShader = ppLights[iCurLight]->m_pShader; WriteString(pShader ? pShader->GetName() : "", fMem); } return 0 == pPak->UpdateFile (pFileName, fMem.GetData(), fMem.GetSize()); } bool CLMSerializationManager2::LoadDLights(const char *pszFileName, CDLight **&ppLightsOut, UINT &iNumLightsOut) const { return true; } // writes the mips to the given DDS // gets the highest level MIP from the dds itself (to the moment there must be the // MIP written to the end of dds file). Returns the number of mips generated // (including already given highest-level mip) unsigned GenerateDDSMips( CTempFile& dds, int wdt, int hgt) { int wd; int i, j; int num; // the size of all MIPs including the highest-level (given) one unsigned numBytes = 0; int w = wdt; int h = hgt; while (w || h) { if (w == 0) w = 1; if (h == 0) h = 1; numBytes += w * h * 4; w >>= 1; h >>= 1; } // the source mip offset: will be changed as the mips are generated sequentially int nOffsetSrcMip = dds.GetSize() - wdt*hgt*4; if (nOffsetSrcMip < 0) return 0; dds.SetSize(nOffsetSrcMip + numBytes); num = 1; // number of mips byte* src = (byte*)dds.GetData() + nOffsetSrcMip; byte* dst = src + wdt*hgt*4; // pointer to next mip wd = wdt<<2; // width of one row of the source mip wdt >>= 1; // next mip dimension hgt >>= 1; while (wdt || hgt) { if (wdt < 1) wdt = 1; if (hgt < 1) hgt = 1; byte* src1 = src; byte* dst1 = dst; for (i=0; i>2; dst1[1] = (src2[1]+src2[5]+src2[wd+1]+src2[wd+5])>>2; dst1[2] = (src2[2]+src2[6]+src2[wd+2]+src2[wd+6])>>2; dst1[3] = (src2[3]+src2[7]+src2[wd+3]+src2[wd+7])>>2; dst1 += 4; // run the target pointer to the next pixel src2 += 8; // run the source pointer to the next 2x2 block } src1 += wd<<1; } src = dst; dst = dst1; num++; wd = wdt<<2; // width of one row of the source mip wdt >>= 1; // next mip dimension hgt >>= 1; } assert (dst == (byte*)dds.GetData() + dds.GetSize()); return num; } static CTempFile* g_pDDSTarget; static unsigned int g_numMips; static bool DDSCompressCallback(void * data, int miplevel, DWORD size) { g_pDDSTarget->WriteData(data, size); return false; } // initializes from raw bitmaps void CLMSerializationManager2::RawLMData::initFromBMP (BitmapEnum t, const void* pSource) { CTempFile* pBMP; switch (t) { case TEX_COLOR: pBMP = &m_ColorLerp4; break; case TEX_DOMDIR: pBMP = &m_DomDirection3; break; case TEX_OCCL: pBMP = &m_Occl2; break; case TEX_HDR: pBMP = &m_HDRColorLerp4; break; default: return; } int nBytesPerPixel = 4; int nBytesReservedPerPixel = 4; switch(t) { case TEX_COLOR: nBytesPerPixel = 4; nBytesReservedPerPixel = 4; break; #ifdef USE_DOT3_ALPHA case TEX_DOMDIR: nBytesPerPixel = 4; nBytesReservedPerPixel = 4; break; #else case TEX_DOMDIR: nBytesPerPixel = 3; nBytesReservedPerPixel = 4; break; #endif case TEX_OCCL: nBytesPerPixel = 2; nBytesReservedPerPixel = 2; break; case TEX_HDR: nBytesPerPixel = 4; nBytesReservedPerPixel = 4; break; } pBMP->Clear(); pBMP->Reserve (sizeof(DWORD) + sizeof(DDS_HEADER) + m_dwWidth*m_dwHeight*nBytesReservedPerPixel); DWORD dwMagic = MAKEFOURCC('D','D','S',' '); pBMP->Write( dwMagic); DDS_HEADER ddsh; ZeroStruct(ddsh); ddsh.dwSize = sizeof(DDS_HEADER); ddsh.dwWidth = m_dwWidth; ddsh.dwHeight = m_dwHeight; if(t == TEX_DOMDIR || t == TEX_COLOR || t == TEX_HDR) { ddsh.dwHeaderFlags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP; ddsh.dwSurfaceFlags = DDS_SURFACE_FLAGS_TEXTURE | DDS_SURFACE_FLAGS_MIPMAP; ddsh.dwMipMapCount = 1; } else { ddsh.dwHeaderFlags = DDS_HEADER_FLAGS_TEXTURE; ddsh.dwSurfaceFlags = DDS_SURFACE_FLAGS_TEXTURE; ddsh.dwMipMapCount = 0; } unsigned nOffsetDDSH = pBMP->GetSize(); if(t == TEX_DOMDIR || t == TEX_COLOR || t == TEX_HDR) ddsh.ddspf = DDSPF_A8R8G8B8; else ddsh.ddspf = DDSPF_A4R4G4B4; pBMP->Write (ddsh); if(t == TEX_DOMDIR || t == TEX_COLOR || t == TEX_HDR) { for (unsigned i = 0; i < m_dwWidth*m_dwHeight; ++i) { const char* pSrc = ((const char*)pSource)+ i * nBytesPerPixel; pBMP->Write(pSrc[2]); pBMP->Write(pSrc[1]); pBMP->Write(pSrc[0]); pBMP->Write((nBytesPerPixel == 4) ? pSrc[3] : (char)0xFF); } unsigned numMips = GenerateDDSMips(*pBMP, m_dwWidth, m_dwHeight); ((DDS_HEADER*)((byte*)pBMP->GetData() + nOffsetDDSH))->dwMipMapCount = numMips; } else { for (unsigned i = 0; i < m_dwWidth*m_dwHeight; ++i) { const char* pSrc = ((const char*)pSource)+ i * nBytesPerPixel;//data already preswizzled into BGRA each 4 bit pBMP->Write(pSrc[0]); pBMP->Write(pSrc[1]); } } } // initializes from files bool CLMSerializationManager2::RawLMData::initFromDDS (BitmapEnum t, ICryPak* pPak, const string& szFileName) { FILE* f = pPak->FOpen (szFileName.c_str(), "rb"); if (!f) return false; AutoFileCloser _AC(f); if (pPak->FSeek(f, 0, SEEK_END)) return false; long nLength = pPak->FTell(f); if (nLength <= 0) return false; if (pPak->FSeek(f, 0, SEEK_SET)) return false; CTempFile* pBMP; switch (t) { case TEX_COLOR: pBMP = &m_ColorLerp4; break; case TEX_DOMDIR: pBMP = &m_DomDirection3; break; case TEX_OCCL: pBMP = &m_Occl2; break; case TEX_HDR: pBMP = &m_HDRColorLerp4; break; default: return false; } pBMP->Init(nLength); if (pPak->FRead(pBMP->GetData(), nLength, 1, f) != 1) { pBMP->Init(0); return false; } return true; }