BVB Source Codes

CRYENGINE Show ObjMan.cpp Source code

Return Download CRYENGINE: download ObjMan.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  File name:   statobjman.cpp
  5. //  Version:     v1.00
  6. //  Created:     28/5/2001 by Vladimir Kajalin
  7. //  Compilers:   Visual Studio.NET
  8. //  Description: Loading trees, buildings, ragister/unregister entities for rendering
  9. // -------------------------------------------------------------------------
  10. //  History:
  11. //
  12. ////////////////////////////////////////////////////////////////////////////
  13.  
  14. #include "StdAfx.h"
  15.  
  16. #include "StatObj.h"
  17. #include "ObjMan.h"
  18. #include "VisAreas.h"
  19. #include "terrain_sector.h"
  20. #include "PolygonClipContext.h"
  21. #include "3dEngine.h"
  22. #include "IndexedMesh.h"
  23. #include "Brush.h"
  24. #include "Vegetation.h"
  25. #include "terrain.h"
  26. #include "ObjectsTree.h"
  27. #include <CrySystem/File/IResourceManager.h>
  28. #include "DecalRenderNode.h"
  29.  
  30. #define BRUSH_LIST_FILE     "brushlist.txt"
  31. #define CGF_LEVEL_CACHE_PAK "cgf.pak"
  32.  
  33. //Platform specific includes MemoryBarrier
  34. #if defined(CRY_PLATFORM_WINDOWS) || defined(CRY_PLATFORM_DURANGO)
  35.         #include <CryCore/Platform/CryWindows.h>
  36. #endif
  37.  
  38. //////////////////////////////////////////////////////////////////////////
  39. IStatObj* CObjManager::GetStaticObjectByTypeID(int nTypeID, int nSID)
  40. {
  41.         assert(nSID >= 0 && nSID < m_lstStaticTypes.Count());
  42.  
  43.         if (nTypeID >= 0 && nTypeID < m_lstStaticTypes[nSID].Count())
  44.                 return m_lstStaticTypes[nSID][nTypeID].pStatObj;
  45.  
  46.         return 0;
  47. }
  48.  
  49. IStatObj* CObjManager::FindStaticObjectByFilename(const char* filename)
  50. {
  51.         return stl::find_in_map(m_nameToObjectMap, CONST_TEMP_STRING(filename), NULL);
  52. }
  53.  
  54. void CObjManager::UnloadVegetationModels(bool bDeleteAll)
  55. {
  56.         for (uint32 nSID = 0; nSID < m_lstStaticTypes.size(); nSID++)
  57.         {
  58.                 PodArray<StatInstGroup>& rGroupTable = m_lstStaticTypes[nSID];
  59.                 for (uint32 nGroupId = 0; nGroupId < rGroupTable.size(); nGroupId++)
  60.                 {
  61.                         StatInstGroup& rGroup = rGroupTable[nGroupId];
  62.  
  63.                         rGroup.pStatObj = NULL;
  64.                         rGroup.pMaterial = NULL;
  65.  
  66.                         for (int j = 0; j < FAR_TEX_COUNT; ++j)
  67.                         {
  68.                                 SVegetationSpriteLightInfo& rLightInfo = rGroup.m_arrSSpriteLightInfo[j];
  69.                                 if (rLightInfo.m_pDynTexture)
  70.                                         SAFE_RELEASE(rLightInfo.m_pDynTexture);
  71.                         }
  72.                 }
  73.  
  74.                 if (bDeleteAll)
  75.                         rGroupTable.Free();
  76.         }
  77. }
  78.  
  79. //////////////////////////////////////////////////////////////////////////
  80. void CObjManager::UnloadObjects(bool bDeleteAll)
  81. {
  82.         UnloadVegetationModels(bDeleteAll);
  83.         UnloadFarObjects();
  84.  
  85.         CleanStreamingData();
  86.  
  87.         if (m_REFarTreeSprites)
  88.                 m_REFarTreeSprites->Release(true);
  89.         m_REFarTreeSprites = 0;
  90.  
  91.         m_pRMBox = 0;
  92.  
  93.         m_decalsToPrecreate.resize(0);
  94.  
  95.         // Clear all objects that are in the garbage collector.
  96.         ClearStatObjGarbage();
  97.  
  98.         stl::free_container(m_checkForGarbage);
  99.         m_bGarbageCollectionEnabled = false;
  100.  
  101.         if (bDeleteAll)
  102.         {
  103.                 m_lockedObjects.clear(); // Lock/Unlock resources will not work with this.
  104.  
  105.                 // Release default stat obj.
  106.                 m_pDefaultCGF = 0;
  107.  
  108.                 m_nameToObjectMap.clear();
  109.                 m_lstLoadedObjects.clear();
  110.  
  111.                 int nNumLeaks = 0;
  112.                 std::vector<CStatObj*> garbage;
  113.                 for (CStatObj* pStatObj = CStatObj::get_intrusive_list_root(); pStatObj; pStatObj = pStatObj->get_next_intrusive())
  114.                 {
  115.                         garbage.push_back(pStatObj);
  116.  
  117. #if !defined(_RELEASE)
  118.                         if (!pStatObj->IsDefaultObject())
  119.                         {
  120.                                 nNumLeaks++;
  121.                                 Warning("StatObj not deleted: %s (%s)  RefCount: %d", pStatObj->m_szFileName.c_str(), pStatObj->m_szGeomName.c_str(), pStatObj->m_nUsers);
  122.                         }
  123. #endif //_RELEASE
  124.                 }
  125.  
  126. #ifndef _RELEASE
  127.                 // deleting leaked objects
  128.                 if (nNumLeaks > 0)
  129.                 {
  130.                         Warning("CObjManager::CheckObjectLeaks: %d object(s) found in memory", nNumLeaks);
  131.                 }
  132. #endif //_RELEASE
  133.  
  134.                 for (int i = 0, num = (int)garbage.size(); i < num; i++)
  135.                 {
  136.                         CStatObj* pStatObj = garbage[i];
  137.                         pStatObj->ShutDown();
  138.                 }
  139.                 for (int i = 0, num = (int)garbage.size(); i < num; i++)
  140.                 {
  141.                         CStatObj* pStatObj = garbage[i];
  142.                         delete pStatObj;
  143.                 }
  144.  
  145. #ifdef POOL_STATOBJ_ALLOCS
  146.                 assert(m_statObjPool->GetTotalMemory().nUsed == 0);
  147. #endif
  148.         }
  149.         m_bGarbageCollectionEnabled = true;
  150.  
  151. #ifdef POOL_STATOBJ_ALLOCS
  152.         m_statObjPool->FreeMemoryIfEmpty();
  153. #endif
  154.  
  155.         stl::free_container(m_lstTmpCastingNodes);
  156.         stl::free_container(m_decalsToPrecreate);
  157.         stl::free_container(m_tmpAreas0);
  158.         stl::free_container(m_tmpAreas1);
  159.         for (size_t rl = 0; rl < MAX_RECURSION_LEVELS; ++rl)
  160.         {
  161.                 for (size_t ti = 0; ti < nThreadsNum; ++ti)
  162.                         stl::free_container(m_arrVegetationSprites[rl][ti]);
  163.         }
  164.         for (int nSID = 0; nSID < m_lstStaticTypes.Count(); nSID++)
  165.                 m_lstStaticTypes[nSID].Free();
  166. }
  167.  
  168. //////////////////////////////////////////////////////////////////////////
  169. void CObjManager::CleanStreamingData()
  170. {
  171.         stl::free_container(m_arrStreamingNodeStack);
  172.  
  173.         stl::free_container(m_arrStreamableToRelease);
  174.         stl::free_container(m_arrStreamableToLoad);
  175.         stl::free_container(m_arrStreamableToDelete);
  176. }
  177.  
  178. //////////////////////////////////////////////////////////////////////////
  179. // class for asyncronous preloading of level CGF's
  180. //////////////////////////////////////////////////////////////////////////
  181. struct CLevelStatObjLoader : public IStreamCallback, public Cry3DEngineBase
  182. {
  183.         int m_nTasksNum;
  184.  
  185.         CLevelStatObjLoader()
  186.         {
  187.                 m_nTasksNum = 0;
  188.         }
  189.  
  190.         void StartStreaming(const char* pFileName)
  191.         {
  192.                 m_nTasksNum++;
  193.  
  194.                 // request the file
  195.                 StreamReadParams params;
  196.                 params.dwUserData = 0;
  197.                 params.nSize = 0;
  198.                 params.pBuffer = NULL;
  199.                 params.nLoadTime = 0;
  200.                 params.nMaxLoadTime = 0;
  201.                 params.ePriority = estpUrgent;
  202.                 GetSystem()->GetStreamEngine()->StartRead(eStreamTaskTypeGeometry, pFileName, this, &params);
  203.         }
  204.  
  205.         virtual void StreamOnComplete(IReadStream* pStream, unsigned nError)
  206.         {
  207.                 if (!nError)
  208.                 {
  209.                         string szName = pStream->GetName();
  210.                         // remove game folder from path
  211.                         const char* szInGameName = strstr(szName, "\\");
  212.                         // load CGF from memory
  213.                         GetObjManager()->LoadStatObj(szInGameName + 1, NULL, NULL, true, 0, pStream->GetBuffer(), pStream->GetBytesRead());
  214.                 }
  215.  
  216.                 m_nTasksNum--;
  217.         }
  218. };
  219.  
  220. //////////////////////////////////////////////////////////////////////////
  221. // Preload in efficient way all CGF's used in level
  222. //////////////////////////////////////////////////////////////////////////
  223. void CObjManager::PreloadLevelObjects()
  224. {
  225.         LOADING_TIME_PROFILE_SECTION;
  226.  
  227.         // Starting a new level, so make sure the round ids are ahead of what they were in the last level
  228.         m_nUpdateStreamingPrioriryRoundId += 8;
  229.         m_nUpdateStreamingPrioriryRoundIdFast += 8;
  230.  
  231.         PrintMessage("Starting loading level CGF's ...");
  232.         INDENT_LOG_DURING_SCOPE();
  233.  
  234.         float fStartTime = GetCurAsyncTimeSec();
  235.  
  236.         bool bCgfCacheExist = false;
  237.         if (GetCVars()->e_StreamCgf != 0)
  238.         {
  239.                 // Only when streaming enable use no-mesh cgf pak.
  240.                 //bCgfCacheExist = GetISystem()->GetIResourceManager()->LoadLevelCachePak( CGF_LEVEL_CACHE_PAK,"" );
  241.         }
  242.         IResourceList* pResList = GetISystem()->GetIResourceManager()->GetLevelResourceList();
  243.  
  244.         // Construct streamer object
  245.         CLevelStatObjLoader cgfStreamer;
  246.  
  247.         CryPathString cgfFilename;
  248.         int nCgfCounter = 0;
  249.         int nInLevelCacheCount = 0;
  250.  
  251.         bool bVerboseLogging = GetCVars()->e_StatObjPreload > 1;
  252.  
  253.         //////////////////////////////////////////////////////////////////////////
  254.         // Enumerate all .CGF inside level from the "brushlist.txt" file.
  255.         {
  256.                 string brushListFilename = Get3DEngine()->GetLevelFilePath(BRUSH_LIST_FILE);
  257.                 CCryFile file;
  258.                 if (file.Open(brushListFilename.c_str(), "rb") && file.GetLength() > 0)
  259.                 {
  260.                         int nFileLength = file.GetLength();
  261.                         char* buf = new char[nFileLength + 1];
  262.                         buf[nFileLength] = 0; // Null terminate
  263.                         file.ReadRaw(buf, nFileLength);
  264.  
  265.                         // Parse file, every line in a file represents a resource filename.
  266.                         char seps[] = "\r\n";
  267.                         char* token = strtok(buf, seps);
  268.                         while (token != NULL)
  269.                         {
  270.                                 int nAliasLen = sizeof("%level%") - 1;
  271.                                 if (strncmp(token, "%level%", nAliasLen) == 0)
  272.                                 {
  273.                                         cgfFilename = Get3DEngine()->GetLevelFilePath(token + nAliasLen);
  274.                                 }
  275.                                 else
  276.                                 {
  277.                                         cgfFilename = token;
  278.                                 }
  279.  
  280.                                 if (bVerboseLogging)
  281.                                 {
  282.                                         CryLog("%s", cgfFilename.c_str());
  283.                                 }
  284.                                 // Do not use streaming for the Brushes from level.pak.
  285.                                 GetObjManager()->LoadStatObj(cgfFilename.c_str(), NULL, 0, false, 0);
  286.                                 //cgfStreamer.StartStreaming(cgfFilename.c_str());
  287.                                 nCgfCounter++;
  288.  
  289.                                 token = strtok(NULL, seps);
  290.  
  291.                                 //This loop can take a few seconds, so we should refresh the loading screen and call the loading tick functions to ensure that no big gaps in coverage occur.
  292.                                 SYNCHRONOUS_LOADING_TICK();
  293.                         }
  294.                         delete[]buf;
  295.                 }
  296.         }
  297.         //////////////////////////////////////////////////////////////////////////
  298.  
  299.         // Request objects loading from Streaming System.
  300.         if (const char* pCgfName = pResList->GetFirst())
  301.         {
  302.                 while (pCgfName)
  303.                 {
  304.                         if (strstr(pCgfName, ".cgf"))
  305.                         {
  306.                                 const char* sLodName = strstr(pCgfName, "_lod");
  307.                                 if (sLodName && (sLodName[4] >= '0' && sLodName[4] <= '9'))
  308.                                 {
  309.                                         // Ignore Lod files.
  310.                                         pCgfName = pResList->GetNext();
  311.                                         continue;
  312.                                 }
  313.  
  314.                                 cgfFilename = pCgfName;
  315.  
  316.                                 if (bVerboseLogging)
  317.                                 {
  318.                                         CryLog("%s", cgfFilename.c_str());
  319.                                 }
  320.                                 CStatObj* pStatObj = GetObjManager()->LoadStatObj(cgfFilename.c_str(), NULL, 0, true, 0);
  321.                                 if (pStatObj)
  322.                                 {
  323.                                         if (pStatObj->m_bMeshStrippedCGF)
  324.                                         {
  325.                                                 nInLevelCacheCount++;
  326.                                         }
  327.                                 }
  328.                                 //cgfStreamer.StartStreaming(cgfFilename.c_str());
  329.                                 nCgfCounter++;
  330.  
  331.                                 //This loop can take a few seconds, so we should refresh the loading screen and call the loading tick functions to ensure that no big gaps in coverage occur.
  332.                                 SYNCHRONOUS_LOADING_TICK();
  333.                         }
  334.  
  335.                         pCgfName = pResList->GetNext();
  336.                 }
  337.         }
  338.  
  339.         //  PrintMessage("Finished requesting level CGF's: %d objects in %.1f sec", nCgfCounter, GetCurAsyncTimeSec()-fStartTime);
  340.  
  341.         // Continue updating streaming system until all CGF's are loaded
  342.         if (cgfStreamer.m_nTasksNum > 0)
  343.         {
  344.                 LOADING_TIME_PROFILE_SECTION_NAMED("CObjManager::PreloadLevelObjects_StreamEngine_Update");
  345.                 GetSystem()->GetStreamEngine()->UpdateAndWait();
  346.         }
  347.  
  348.         if (bCgfCacheExist)
  349.         {
  350.                 //GetISystem()->GetIResourceManager()->UnloadLevelCachePak( CGF_LEVEL_CACHE_PAK );
  351.         }
  352.  
  353.         float dt = GetCurAsyncTimeSec() - fStartTime;
  354.         PrintMessage("Finished loading level CGF's: %d objects loaded (%d from LevelCache) in %.1f sec", nCgfCounter, nInLevelCacheCount, dt);
  355. }
  356.  
  357. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  358. // Create / delete object
  359. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  360. CStatObj* CObjManager::LoadStatObj(const char* __szFileName
  361.                                    , const char* _szGeomName, IStatObj::SSubObject** ppSubObject
  362.                                    , bool bUseStreaming
  363.                                    , unsigned long nLoadingFlags
  364.                                    , const void* pData
  365.                                    , int nDataSize
  366.                                    , const char* szBlockName)
  367. {
  368.         if (!m_pDefaultCGF && strcmp(__szFileName, DEFAULT_CGF_NAME) != 0)
  369.         {
  370.                 // Load default object if not yet loaded.
  371.                 const char* sDefaulObjFilename = DEFAULT_CGF_NAME;
  372.                 // prepare default object
  373.                 m_pDefaultCGF = LoadStatObj(sDefaulObjFilename, NULL, NULL, false, nLoadingFlags);
  374.                 if (!m_pDefaultCGF)
  375.                 {
  376.                         Error("CObjManager::LoadStatObj: Default object not found (%s)", sDefaulObjFilename);
  377.                         m_pDefaultCGF = new CStatObj();
  378.                 }
  379.                 m_pDefaultCGF->m_bDefaultObject = true;
  380.         }
  381.  
  382.         LOADING_TIME_PROFILE_SECTION_ARGS(__szFileName);
  383.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Static Geometry");
  384.  
  385.         if (ppSubObject)
  386.                 *ppSubObject = NULL;
  387.  
  388.         if (!strcmp(__szFileName, "NOFILE"))
  389.         {
  390.                 // make empty object to be filled from outside
  391.                 CStatObj* pObject = new CStatObj();
  392.                 m_lstLoadedObjects.insert(pObject);
  393.                 return pObject;
  394.         }
  395.  
  396.         // Normalize file name
  397.         char sFilename[_MAX_PATH];
  398.  
  399.         //////////////////////////////////////////////////////////////////////////
  400.         // Remap %level% alias if needed an unify filename
  401.         {
  402.                 int nAliasNameLen = sizeof("%level%") - 1;
  403.                 if (strncmp(__szFileName, "%level%", nAliasNameLen) == 0)
  404.                 {
  405. #ifdef SEG_WORLD
  406.                         string tempString = szBlockName + string(__szFileName + nAliasNameLen + 1);
  407.                         cry_strcpy(sFilename, Get3DEngine()->GetLevelFilePath(tempString.c_str()));
  408. #else
  409.                         cry_strcpy(sFilename, Get3DEngine()->GetLevelFilePath(__szFileName + nAliasNameLen));
  410. #endif
  411.                 }
  412.                 else
  413.                 {
  414.                         cry_strcpy(sFilename, __szFileName);
  415.                 }
  416.  
  417.                 PREFAST_SUPPRESS_WARNING(6054)                                     // sFilename is null terminated
  418.                 std::replace(sFilename, sFilename + strlen(sFilename), '\\', '/'); // To Unix Path
  419.         }
  420.         //////////////////////////////////////////////////////////////////////////
  421.  
  422.         bool bForceBreakable = strstr(sFilename, "break") != 0;
  423.         if (_szGeomName && !strcmp(_szGeomName, "#ForceBreakable"))
  424.         {
  425.                 bForceBreakable = true;
  426.                 _szGeomName = 0;
  427.         }
  428.  
  429.         // Try to find already loaded object
  430.         CStatObj* pObject = 0;
  431.  
  432.         int flagCloth = 0;
  433.         if (_szGeomName && !strcmp(_szGeomName, "cloth"))
  434.                 _szGeomName = 0, flagCloth = STATIC_OBJECT_DYNAMIC | STATIC_OBJECT_CLONE;
  435.         else
  436.         {
  437.                 pObject = stl::find_in_map(m_nameToObjectMap, CONST_TEMP_STRING(sFilename), NULL);
  438.                 if (pObject)
  439.                 {
  440.                         if (!bUseStreaming && pObject->m_bCanUnload)
  441.                         {
  442.                                 pObject->DisableStreaming();
  443.                         }
  444.  
  445.                         assert(!pData);
  446.                         if (!pObject->m_bLodsLoaded && !pData)
  447.                         {
  448.                                 pObject->LoadLowLODs(bUseStreaming, nLoadingFlags);
  449.                         }
  450.  
  451.                         if (_szGeomName && _szGeomName[0])
  452.                         {
  453.                                 // Return SubObject.
  454.                                 CStatObj::SSubObject* pSubObject = pObject->FindSubObject(_szGeomName);
  455.                                 if (!pSubObject || !pSubObject->pStatObj)
  456.                                         return 0;
  457.                                 if (pSubObject->pStatObj)
  458.                                 {
  459.                                         if (ppSubObject)
  460.                                                 *ppSubObject = pSubObject;
  461.                                         return (CStatObj*)pSubObject->pStatObj;
  462.                                 }
  463.                         }
  464.                         return pObject;
  465.                 }
  466.         }
  467.  
  468.         // Load new CGF
  469.         pObject = new CStatObj();
  470.         pObject->m_nFlags |= flagCloth;
  471.  
  472.         bUseStreaming &= (GetCVars()->e_StreamCgf != 0);
  473.  
  474.         if (bUseStreaming)
  475.                 pObject->m_bCanUnload = true;
  476.         if (bForceBreakable)
  477.                 nLoadingFlags |= IStatObj::ELoadingFlagsForceBreakable;
  478.  
  479.         if (!pObject->LoadCGF(sFilename, strstr(sFilename, "_lod") != NULL, nLoadingFlags, pData, nDataSize))
  480.         {
  481.                 Error("Failed to load cgf: %s", __szFileName);
  482.                 // object not found
  483.                 // if geom name is specified - just return 0
  484.                 if (_szGeomName && _szGeomName[0])
  485.                 {
  486.                         delete pObject;
  487.                         return 0;
  488.                 }
  489.  
  490.                 // make unique default CGF for every case of missing CGF, this will make export process more reliable and help finding missing CGF's in pure game
  491.                 /*              pObject->m_bCanUnload = false;
  492.                     if (m_bEditor && pObject->LoadCGF( DEFAULT_CGF_NAME, false, nLoadingFlags, pData, nDataSize ))
  493.                     {
  494.                       pObject->m_szFileName = sFilename;
  495.                       pObject->m_bDefaultObject = true;
  496.                     }
  497.                     else*/
  498.                 {
  499.                         delete pObject;
  500.                         return m_pDefaultCGF;
  501.                 }
  502.         }
  503.  
  504.         // now try to load lods
  505.         if (!pData)
  506.         {
  507.                 pObject->LoadLowLODs(bUseStreaming, nLoadingFlags);
  508.         }
  509.  
  510.         if (!pObject->m_bCanUnload)
  511.         {
  512.                 // even if streaming is disabled we register object for potential streaming (streaming system will never unload it)
  513.                 pObject->DisableStreaming();
  514.         }
  515.  
  516.         // sub meshes merging
  517.         pObject->TryMergeSubObjects(false);
  518.  
  519.         m_lstLoadedObjects.insert(pObject);
  520.         m_nameToObjectMap[pObject->m_szFileName] = pObject;
  521.  
  522.         if (_szGeomName && _szGeomName[0])
  523.         {
  524.                 // Return SubObject.
  525.                 CStatObj::SSubObject* pSubObject = pObject->FindSubObject(_szGeomName);
  526.                 if (!pSubObject || !pSubObject->pStatObj)
  527.                         return 0;
  528.                 if (pSubObject->pStatObj)
  529.                 {
  530.                         if (ppSubObject)
  531.                                 *ppSubObject = pSubObject;
  532.                         return (CStatObj*)pSubObject->pStatObj;
  533.                 }
  534.         }
  535.  
  536.         return pObject;
  537. }
  538.  
  539. //////////////////////////////////////////////////////////////////////////
  540. bool CObjManager::InternalDeleteObject(CStatObj* pObject)
  541. {
  542.         assert(pObject);
  543.  
  544.         if (!m_bLockCGFResources && !IsResourceLocked(pObject->m_szFileName))
  545.         {
  546.                 LoadedObjects::iterator it = m_lstLoadedObjects.find(pObject);
  547.                 if (it != m_lstLoadedObjects.end())
  548.                 {
  549.                         m_lstLoadedObjects.erase(it);
  550.                         m_nameToObjectMap.erase(pObject->m_szFileName);
  551.                 }
  552.                 else
  553.                 {
  554.                         //Warning( "CObjManager::ReleaseObject called on object not loaded in ObjectManager %s",pObject->m_szFileName.c_str() );
  555.                         //return false;
  556.                 }
  557.  
  558.                 delete pObject;
  559.                 return true;
  560.         }
  561.         else if (m_bLockCGFResources)
  562.         {
  563.                 // Put them to locked stat obj list.
  564.                 stl::push_back_unique(m_lockedObjects, pObject);
  565.         }
  566.  
  567.         return false;
  568. }
  569.  
  570. CStatObj* CObjManager::AllocateStatObj()
  571. {
  572. #ifdef POOL_STATOBJ_ALLOCS
  573.         return (CStatObj*)m_statObjPool->Allocate();
  574. #else
  575.         return (CStatObj*)malloc(sizeof(CStatObj));
  576. #endif
  577. }
  578.  
  579. void CObjManager::FreeStatObj(CStatObj* pObj)
  580. {
  581. #ifdef POOL_STATOBJ_ALLOCS
  582.         m_statObjPool->Deallocate(pObj);
  583. #else
  584.         free(pObj);
  585. #endif
  586. }
  587.  
  588. CObjManager::CObjManager() :
  589.         m_pDefaultCGF(NULL),
  590.         m_decalsToPrecreate(),
  591.         m_bNeedProcessObjectsStreaming_Finish(false),
  592.         m_CullThread()
  593. {
  594. #ifdef POOL_STATOBJ_ALLOCS
  595.         m_statObjPool = new stl::PoolAllocator<sizeof(CStatObj), stl::PSyncMultiThread, alignof(CStatObj)>(stl::FHeap().PageSize(64)); // 20Kb per page
  596. #endif
  597.  
  598.         m_vStreamPreCachePointDefs.Add(SObjManPrecachePoint());
  599.         m_vStreamPreCacheCameras.Add(SObjManPrecacheCamera());
  600.         m_nNextPrecachePointId = 0;
  601.         m_bCameraPrecacheOverridden = false;
  602.  
  603.         m_pObjManager = this;
  604.  
  605.         m_fCurrTime = 0.0f;
  606.  
  607.         m_vSkyColor.Set(0, 0, 0);
  608.         m_fSunSkyRel = 0;
  609.         m_vSunColor.Set(0, 0, 0);
  610.         m_fILMul = 1.0f;
  611.         m_fSkyBrightMul = 0.3f;
  612.         m_fSSAOAmount = 1.f;
  613.         m_fSSAOContrast = 1.f;
  614.         m_fGIAmount = 1.f;
  615.         m_rainParams.nUpdateFrameID = -1;
  616.         m_rainParams.fAmount = 0.f;
  617.         m_rainParams.fRadius = 1.f;
  618.         m_rainParams.vWorldPos.Set(0, 0, 0);
  619.         m_rainParams.vColor.Set(1, 1, 1);
  620.         m_rainParams.fFakeGlossiness = 0.5f;
  621.         m_rainParams.fFakeReflectionAmount = 1.5f;
  622.         m_rainParams.fDiffuseDarkening = 0.5f;
  623.         m_rainParams.fRainDropsAmount = 0.5f;
  624.         m_rainParams.fRainDropsSpeed = 1.f;
  625.         m_rainParams.fRainDropsLighting = 1.f;
  626.         m_rainParams.fMistAmount = 3.f;
  627.         m_rainParams.fMistHeight = 8.f;
  628.         m_rainParams.fPuddlesAmount = 1.5f;
  629.         m_rainParams.fPuddlesMaskAmount = 1.0f;
  630.         m_rainParams.fPuddlesRippleAmount = 2.0f;
  631.         m_rainParams.fSplashesAmount = 1.3f;
  632.         m_rainParams.bIgnoreVisareas = false;
  633.         m_rainParams.bDisableOcclusion = false;
  634.  
  635.         m_fMaxViewDistanceScale = 1.f;
  636.         m_fGSMMaxDistance = 0;
  637.         m_bLockCGFResources = false;
  638.  
  639.         m_pRMBox = NULL;
  640.         m_bGarbageCollectionEnabled = true;
  641.  
  642.         m_decalsToPrecreate.reserve(128);
  643.         m_REFarTreeSprites = 0;
  644.  
  645.         // init queue for check occlusion
  646.         m_CheckOcclusionQueue.Init(GetCVars()->e_CheckOcclusionQueueSize);
  647.         m_CheckOcclusionOutputQueue.Init(GetCVars()->e_CheckOcclusionOutputQueueSize);
  648. }
  649.  
  650. // make unit box for occlusion test
  651. void CObjManager::MakeUnitCube()
  652. {
  653.         if (m_pRMBox)
  654.                 return;
  655.  
  656.         SVF_P3F_C4B_T2F arrVerts[8];
  657.         arrVerts[0].xyz = Vec3(0, 0, 0);
  658.         arrVerts[1].xyz = Vec3(1, 0, 0);
  659.         arrVerts[2].xyz = Vec3(0, 0, 1);
  660.         arrVerts[3].xyz = Vec3(1, 0, 1);
  661.         arrVerts[4].xyz = Vec3(0, 1, 0);
  662.         arrVerts[5].xyz = Vec3(1, 1, 0);
  663.         arrVerts[6].xyz = Vec3(0, 1, 1);
  664.         arrVerts[7].xyz = Vec3(1, 1, 1);
  665.  
  666.         //              6-------7
  667.         //       /                 /|
  668.         //      2-------3       |
  669.         //      |             | |
  670.         //      |       4                       | 5
  671.         //      |                               |/
  672.         //      0-------1
  673.  
  674.         static const vtx_idx arrIndices[] =
  675.         {
  676.                 // front + back
  677.                 1, 0, 2,
  678.                 2, 3, 1,
  679.                 5, 6, 4,
  680.                 5, 7, 6,
  681.                 // left + right
  682.                 0, 6, 2,
  683.                 0, 4, 6,
  684.                 1, 3, 7,
  685.                 1, 7, 5,
  686.                 // top + bottom
  687.                 3, 2, 6,
  688.                 6, 7, 3,
  689.                 1, 4, 0,
  690.                 1, 5, 4
  691.         };
  692.  
  693.         m_pRMBox = GetRenderer()->CreateRenderMeshInitialized(
  694.           arrVerts,
  695.           CRY_ARRAY_COUNT(arrVerts),
  696.           eVF_P3F_C4B_T2F,
  697.           arrIndices,
  698.           CRY_ARRAY_COUNT(arrIndices),
  699.           prtTriangleList,
  700.           "OcclusionQueryCube", "OcclusionQueryCube",
  701.           eRMT_Static);
  702.  
  703.         m_pRMBox->SetChunk(NULL, 0, CRY_ARRAY_COUNT(arrVerts), 0, CRY_ARRAY_COUNT(arrIndices), 1.0f, 0);
  704.  
  705.         m_bGarbageCollectionEnabled = true;
  706. }
  707.  
  708. CObjManager::~CObjManager()
  709. {
  710.         // free default object
  711.         m_pDefaultCGF = 0;
  712.  
  713.         // free brushes
  714.         /*  assert(!m_lstBrushContainer.Count());
  715.            for(int i=0; i<m_lstBrushContainer.Count(); i++)
  716.            {
  717.             if(m_lstBrushContainer[i]->GetEntityStatObj())
  718.               ReleaseObject((CStatObj*)m_lstBrushContainer[i]->GetEntityStatObj());
  719.             delete m_lstBrushContainer[i];
  720.            }
  721.            m_lstBrushContainer.Reset();
  722.          */
  723.         UnloadObjects(true);
  724. #ifdef POOL_STATOBJ_ALLOCS
  725.         delete m_statObjPool;
  726. #endif
  727. }
  728.  
  729. int CObjManager::ComputeDissolve(const CLodValue &lodValueIn, IRenderNode* pEnt, float fEntDistance, CLodValue arrlodValuesOut[2])
  730. {
  731.         int nLodMain = CLAMP(0, lodValueIn.LodA(), MAX_STATOBJ_LODS_NUM - 1);
  732.         int nLodMin = max(nLodMain - 1, 0);
  733.         int nLodMax = min(nLodMain + 1, MAX_STATOBJ_LODS_NUM - 1);
  734.  
  735.         float prevLodLastTimeUsed = 0;
  736.         float * arrLodLastTimeUsed = pEnt->m_pTempData->userData.arrLodLastTimeUsed;
  737.  
  738.         // Find when previous lod was used as primary lod last time and update last time used for current primary lod
  739.         for (int nLO = nLodMin; nLO <= nLodMax; nLO++)
  740.         {
  741.                 if (nLodMain != nLO)
  742.                 {
  743.                         if (arrLodLastTimeUsed[nLO] > prevLodLastTimeUsed)
  744.                         {
  745.                                 prevLodLastTimeUsed = arrLodLastTimeUsed[nLO];
  746.                         }
  747.                 }
  748.  
  749.                 if (nLodMain == nLO)
  750.                         arrLodLastTimeUsed[nLO] = GetCurTimeSec();
  751.         }
  752.  
  753.         float fDissolveRef = 1.f - SATURATE((GetCurTimeSec() - prevLodLastTimeUsed) / GetCVars()->e_LodTransitionTime);
  754.  
  755.         prevLodLastTimeUsed = max(prevLodLastTimeUsed, GetCurTimeSec() - GetCVars()->e_LodTransitionTime);
  756.  
  757.         // Compute also max view distance fading
  758.         const float fDistFadeInterval = 2.f;
  759.         float fDistFadeRef = SATURATE(min(fEntDistance / pEnt->m_fWSMaxViewDist * 5.f - 4.f, ((fEntDistance - pEnt->m_fWSMaxViewDist) / fDistFadeInterval + 1.f)));
  760.  
  761.         int nLodsNum = 0;
  762.  
  763.         // Render current lod and (if needed) previous lod
  764.         for (int nLO = nLodMin; nLO <= nLodMax && nLodsNum<2; nLO++)
  765.         {
  766.                 if (arrLodLastTimeUsed[nLO] < prevLodLastTimeUsed)
  767.                         continue;
  768.  
  769.                 CLodValue lodSubValue;
  770.  
  771.                 if (nLodMain == nLO)
  772.                 {
  773.                         // Incoming LOD
  774.  
  775.                         float fDissolveMaxDistRef = max(fDissolveRef, fDistFadeRef);
  776.  
  777.                         lodSubValue = CLodValue(nLO, int(fDissolveMaxDistRef*255.f), -1);
  778.                 }
  779.                 else
  780.                 {
  781.                         // Out-coming LOD
  782.  
  783.                         float fDissolveMaxDistRef = min(fDissolveRef, 1.f - fDistFadeRef);
  784.  
  785.                         lodSubValue = CLodValue(-1, int(fDissolveMaxDistRef*255.f), nLO);
  786.                 }
  787.  
  788.                 arrlodValuesOut[nLodsNum] = lodSubValue;
  789.                 nLodsNum++;
  790.         }
  791.  
  792.         return nLodsNum;
  793. }
  794.  
  795. // mostly xy size
  796. float CObjManager::GetXYRadius(int type, int nSID)
  797. {
  798.         assert(nSID >= 0 && nSID < m_lstStaticTypes.Count());
  799.  
  800.         if ((m_lstStaticTypes[nSID].Count() <= type || !m_lstStaticTypes[nSID][type].pStatObj))
  801.                 return 0;
  802.  
  803.         Vec3 vSize = m_lstStaticTypes[nSID][type].pStatObj->GetBoxMax() - m_lstStaticTypes[nSID][type].pStatObj->GetBoxMin();
  804.         vSize.z *= 0.5f;
  805.  
  806.         float fXYRadius = vSize.GetLength() * 0.5f;
  807.  
  808.         return fXYRadius;
  809. }
  810.  
  811. bool CObjManager::GetStaticObjectBBox(int nType, Vec3& vBoxMin, Vec3& vBoxMax, int nSID)
  812. {
  813.         assert(nSID >= 0 && nSID < m_lstStaticTypes.Count());
  814.  
  815.         if ((m_lstStaticTypes[nSID].Count() <= nType || !m_lstStaticTypes[nSID][nType].pStatObj))
  816.                 return 0;
  817.  
  818.         vBoxMin = m_lstStaticTypes[nSID][nType].pStatObj->GetBoxMin();
  819.         vBoxMax = m_lstStaticTypes[nSID][nType].pStatObj->GetBoxMax();
  820.  
  821.         return true;
  822. }
  823.  
  824. void CObjManager::GetMemoryUsage(class ICrySizer* pSizer) const
  825. {
  826.         {
  827.                 SIZER_COMPONENT_NAME(pSizer, "Self");
  828.                 pSizer->AddObject(this, sizeof(*this));
  829.         }
  830.  
  831.         {
  832.                 SIZER_COMPONENT_NAME(pSizer, "StaticTypes");
  833.                 pSizer->AddObject(m_lstStaticTypes);
  834.         }
  835.  
  836.         for (int i = 0; i < MAX_RECURSION_LEVELS; i++)
  837.         {
  838.                 SIZER_COMPONENT_NAME(pSizer, "VegetationSprites");
  839.                 for (int t = 0; t < nThreadsNum; t++)
  840.                 {
  841.                         pSizer->AddObject(m_arrVegetationSprites[i][t]);
  842.                 }
  843.         }
  844.  
  845.         {
  846.                 SIZER_COMPONENT_NAME(pSizer, "CMesh");
  847.                 CIndexedMesh* pMesh = CIndexedMesh::get_intrusive_list_root();
  848.                 while (pMesh)
  849.                 {
  850.                         pSizer->AddObject(pMesh);
  851.                         pMesh = pMesh->get_next_intrusive();
  852.                 }
  853.         }
  854.  
  855.         {
  856.                 SIZER_COMPONENT_NAME(pSizer, "StatObj");
  857.                 for (CStatObj* pStatObj = CStatObj::get_intrusive_list_root(); pStatObj; pStatObj = pStatObj->get_next_intrusive())
  858.                 {
  859.                         pStatObj->GetMemoryUsage(pSizer);
  860.                 }
  861.         }
  862.  
  863.         {
  864.                 SIZER_COMPONENT_NAME(pSizer, "EmptyNodes");
  865.                 pSizer->AddObject(COctreeNode::m_arrEmptyNodes);
  866.         }
  867. }
  868.  
  869. // retrieves the bandwidth calculations for the audio streaming
  870. void CObjManager::GetBandwidthStats(float* fBandwidthRequested)
  871. {
  872. #if !defined (_RELEASE) || defined(ENABLE_STATOSCOPE_RELEASE)
  873.         if (fBandwidthRequested && CStatObj::s_fStreamingTime != 0.0f)
  874.         {
  875.                 *fBandwidthRequested = (CStatObj::s_nBandwidth / CStatObj::s_fStreamingTime) / 1024.0f;
  876.         }
  877. #endif
  878. }
  879.  
  880. void CObjManager::ReregisterEntitiesInArea(Vec3 vBoxMin, Vec3 vBoxMax)
  881. {
  882.         PodArray<SRNInfo> lstEntitiesInArea;
  883.  
  884.         AABB vBoxAABB(vBoxMin, vBoxMax);
  885.  
  886.         Get3DEngine()->MoveObjectsIntoListGlobal(&lstEntitiesInArea, &vBoxAABB, true);
  887.  
  888.         if (GetVisAreaManager())
  889.                 GetVisAreaManager()->MoveObjectsIntoList(&lstEntitiesInArea, vBoxAABB, true);
  890.  
  891.         int nChanged = 0;
  892.         for (int i = 0; i < lstEntitiesInArea.Count(); i++)
  893.         {
  894.                 IVisArea* pPrevArea = lstEntitiesInArea[i].pNode->GetEntityVisArea();
  895.                 Get3DEngine()->UnRegisterEntityDirect(lstEntitiesInArea[i].pNode);
  896.  
  897.                 if (lstEntitiesInArea[i].pNode->GetRenderNodeType() == eERType_Decal)
  898.                         ((CDecalRenderNode*)lstEntitiesInArea[i].pNode)->RequestUpdate();
  899.  
  900.                 Get3DEngine()->RegisterEntity(lstEntitiesInArea[i].pNode);
  901.                 if (pPrevArea != lstEntitiesInArea[i].pNode->GetEntityVisArea())
  902.                         nChanged++;
  903.         }
  904. }
  905.  
  906. void CObjManager::FreeNotUsedCGFs()
  907. {
  908.         //assert(!m_bLockCGFResources);
  909.         m_lockedObjects.clear();
  910.  
  911.         if (!m_bLockCGFResources)
  912.         {
  913.                 //Timur, You MUST use next here, or with erase you invalidating
  914.                 LoadedObjects::iterator next;
  915.                 for (LoadedObjects::iterator it = m_lstLoadedObjects.begin(); it != m_lstLoadedObjects.end(); it = next)
  916.                 {
  917.                         next = it;
  918.                         ++next;
  919.                         CStatObj* p = (CStatObj*)(*it);
  920.                         if (p->m_nUsers <= 0)
  921.                         {
  922.                                 CheckForGarbage(p);
  923.                         }
  924.                 }
  925.         }
  926.  
  927.         ClearStatObjGarbage();
  928. }
  929.  
  930. //////////////////////////////////////////////////////////////////////////
  931. void CObjManager::GetLoadedStatObjArray(IStatObj** pObjectsArray, int& nCount)
  932. {
  933.         if (!pObjectsArray)
  934.         {
  935.                 nCount = m_lstLoadedObjects.size();
  936.                 return;
  937.         }
  938.  
  939.         CObjManager::LoadedObjects::iterator it = m_lstLoadedObjects.begin();
  940.         for (int i = 0; i < nCount && it != m_lstLoadedObjects.end(); ++i, ++it)
  941.         {
  942.                 pObjectsArray[i] = *it;
  943.         }
  944. }
  945.  
  946. void StatInstGroup::Update(CVars* pCVars, int nGeomDetailScreenRes)
  947. {
  948.         m_dwRndFlags = 0;
  949.  
  950.         static ICVar* pObjShadowCastSpec = gEnv->pConsole->GetCVar("e_ObjShadowCastSpec");
  951.         if (nCastShadowMinSpec <= pObjShadowCastSpec->GetIVal())
  952.         {
  953.                 m_dwRndFlags |= ERF_CASTSHADOWMAPS | ERF_HAS_CASTSHADOWMAPS;
  954.         }
  955.  
  956.         if (bDynamicDistanceShadows)
  957.                 m_dwRndFlags |= ERF_DYNAMIC_DISTANCESHADOWS;
  958.         if (bHideability)
  959.                 m_dwRndFlags |= ERF_HIDABLE;
  960.         if (bHideabilitySecondary)
  961.                 m_dwRndFlags |= ERF_HIDABLE_SECONDARY;
  962.         if (bPickable)
  963.                 m_dwRndFlags |= ERF_PICKABLE;
  964.         if (!bAllowIndoor)
  965.                 m_dwRndFlags |= ERF_OUTDOORONLY;
  966.         if (bGIMode)
  967.                 m_dwRndFlags |= ERF_GI_MODE_BIT0; // corresponds to IRenderNode::eGM_StaticVoxelization
  968.  
  969.         uint32 nSpec = (uint32)minConfigSpec;
  970.         if (nSpec != 0)
  971.         {
  972.                 m_dwRndFlags &= ~ERF_SPEC_BITS_MASK;
  973.                 m_dwRndFlags |= (nSpec << ERF_SPEC_BITS_SHIFT) & ERF_SPEC_BITS_MASK;
  974.         }
  975.  
  976.         if (GetStatObj())
  977.         {
  978.                 fVegRadiusVert = GetStatObj()->GetRadiusVert();
  979.                 fVegRadiusHor = GetStatObj()->GetRadiusHors();
  980.                 fVegRadius = max(fVegRadiusVert, fVegRadiusHor);
  981.         }
  982.         else
  983.         {
  984.                 fVegRadiusHor = fVegRadius = fVegRadiusVert = 0;
  985.         }
  986.  
  987.         if (bUseSprites && fVegRadius > 0)
  988.         {
  989.                 m_fSpriteSwitchDist = 18.f * fVegRadius * fSize *
  990.                                       max(pCVars->e_VegetationSpritesDistanceCustomRatioMin, fSpriteDistRatio);
  991.                 m_fSpriteSwitchDist *= pCVars->e_VegetationSpritesDistanceRatio;
  992.                 m_fSpriteSwitchDist *= max(1.f, (float)nGeomDetailScreenRes / 1024.f);
  993.                 if (m_fSpriteSwitchDist < pCVars->e_VegetationSpritesMinDistance)
  994.                         m_fSpriteSwitchDist = pCVars->e_VegetationSpritesMinDistance;
  995.         }
  996.         else
  997.                 m_fSpriteSwitchDist = 1000000.f;
  998.  
  999.         for (int j = 0; j < FAR_TEX_COUNT; ++j)
  1000.         {
  1001.                 SVegetationSpriteLightInfo& rLightInfo = m_arrSSpriteLightInfo[j];
  1002.                 if (rLightInfo.m_pDynTexture)
  1003.                         rLightInfo.m_pDynTexture->SetFlags(rLightInfo.m_pDynTexture->GetFlags() | IDynTexture::fNeedRegenerate);
  1004.         }
  1005.  
  1006. #if defined(FEATURE_SVO_GI)
  1007.         IMaterial* pMat = pMaterial ? pMaterial.get() : (pStatObj ? pStatObj->GetMaterial() : 0);
  1008.         if (pMat && (Cry3DEngineBase::GetCVars()->e_svoTI_Active >= 0) && (gEnv->IsEditor() || Cry3DEngineBase::GetCVars()->e_svoTI_Apply))
  1009.                 pMat->SetKeepLowResSysCopyForDiffTex();
  1010. #endif
  1011. }
  1012.  
  1013. float StatInstGroup::GetAlignToTerrainAmount() const
  1014. {
  1015.         return fAlignToTerrainCoefficient;
  1016. }
  1017.  
  1018. bool CObjManager::SphereRenderMeshIntersection(IRenderMesh* pRenderMesh, const Vec3& vInPos, const float fRadius, IMaterial* pMat)
  1019. {
  1020.         FUNCTION_PROFILER_3DENGINE;
  1021.  
  1022.         // get position offset and stride
  1023.         int nPosStride = 0;
  1024.         byte* pPos = pRenderMesh->GetPosPtr(nPosStride, FSL_READ);
  1025.  
  1026.         // get indices
  1027.         vtx_idx* pInds = pRenderMesh->GetIndexPtr(FSL_READ);
  1028.         int nInds = pRenderMesh->GetIndicesCount();
  1029.         assert(nInds % 3 == 0);
  1030.  
  1031.         // test tris
  1032.         TRenderChunkArray& Chunks = pRenderMesh->GetChunks();
  1033.         for (int nChunkId = 0; nChunkId < Chunks.size(); nChunkId++)
  1034.         {
  1035.                 CRenderChunk* pChunk = &Chunks[nChunkId];
  1036.                 if (pChunk->m_nMatFlags & MTL_FLAG_NODRAW || !pChunk->pRE)
  1037.                         continue;
  1038.  
  1039.                 // skip transparent and alpha test
  1040.                 if (pMat)
  1041.                 {
  1042.                         const SShaderItem& shaderItem = pMat->GetShaderItem(pChunk->m_nMatID);
  1043.                         if (!shaderItem.m_pShader || shaderItem.m_pShader->GetFlags() & EF_NODRAW)
  1044.                                 continue;
  1045.                 }
  1046.  
  1047.                 int nLastIndexId = pChunk->nFirstIndexId + pChunk->nNumIndices;
  1048.                 for (int i = pChunk->nFirstIndexId; i < nLastIndexId; i += 3)
  1049.                 {
  1050.                         assert((int)pInds[i + 0] < pRenderMesh->GetVerticesCount());
  1051.                         assert((int)pInds[i + 1] < pRenderMesh->GetVerticesCount());
  1052.                         assert((int)pInds[i + 2] < pRenderMesh->GetVerticesCount());
  1053.  
  1054.                         // get triangle vertices
  1055.                         Vec3 v0 = (*(Vec3*)&pPos[nPosStride * pInds[i + 0]]);
  1056.                         Vec3 v1 = (*(Vec3*)&pPos[nPosStride * pInds[i + 1]]);
  1057.                         Vec3 v2 = (*(Vec3*)&pPos[nPosStride * pInds[i + 2]]);
  1058.  
  1059.                         AABB triBox;
  1060.                         triBox.min = v0;
  1061.                         triBox.max = v0;
  1062.                         triBox.Add(v1);
  1063.                         triBox.Add(v2);
  1064.  
  1065.                         if (Overlap::Sphere_AABB(Sphere(vInPos, fRadius), triBox))
  1066.                                 return true;
  1067.                 }
  1068.         }
  1069.  
  1070.         return false;
  1071. }
  1072.  
  1073. //////////////////////////////////////////////////////////////////////////
  1074. void CObjManager::ClearStatObjGarbage()
  1075. {
  1076.         FUNCTION_PROFILER_3DENGINE;
  1077.  
  1078.         std::vector<CStatObj*> garbage;
  1079.  
  1080.         CryMT::vector<CStatObj*>::AutoLock lock(m_checkForGarbage.get_lock());
  1081.  
  1082.         while (!m_checkForGarbage.empty())
  1083.         {
  1084.                 garbage.resize(0);
  1085.  
  1086.                 // Make sure all stat objects inside this array are unique.
  1087.                 if (!m_checkForGarbage.empty())
  1088.                 {
  1089.                         // Only check explicitly added objects.
  1090.                         // First ShutDown object clearing all pointers.
  1091.                         CStatObj* pStatObj;
  1092.                         while (m_checkForGarbage.try_pop_back(pStatObj))
  1093.                         {
  1094.                                 if (pStatObj->m_bCheckGarbage)
  1095.                                 {
  1096.                                         // Check if it must be released.
  1097.                                         int nChildRefs = pStatObj->CountChildReferences();
  1098.                                         if (pStatObj->m_nUsers <= 0 && nChildRefs <= 0)
  1099.                                         {
  1100.                                                 garbage.push_back(pStatObj);
  1101.                                         }
  1102.                                         else
  1103.                                         {
  1104.                                                 pStatObj->m_bCheckGarbage = false;
  1105.                                         }
  1106.                                 }
  1107.                         }
  1108.                 }
  1109.  
  1110.                 // First ShutDown object clearing all pointers.
  1111.                 for (int i = 0, num = (int)garbage.size(); i < num; i++)
  1112.                 {
  1113.                         CStatObj* pStatObj = garbage[i];
  1114.  
  1115.                         if (!m_bLockCGFResources && !IsResourceLocked(pStatObj->m_szFileName))
  1116.                         {
  1117.                                 // only shutdown object if it can be deleted by InternalDeleteObject()
  1118.                                 pStatObj->ShutDown();
  1119.                         }
  1120.                 }
  1121.  
  1122.                 // Then delete all garbage objects.
  1123.                 for (int i = 0, num = (int)garbage.size(); i < num; i++)
  1124.                 {
  1125.                         CStatObj* pStatObj = garbage[i];
  1126.                         InternalDeleteObject(pStatObj);
  1127.                 }
  1128.  
  1129.         }
  1130. }
  1131.  
  1132. //////////////////////////////////////////////////////////////////////////
  1133. IRenderMesh* CObjManager::GetRenderMeshBox()
  1134. {
  1135.         if (!m_pRMBox)
  1136.         {
  1137.                 MakeUnitCube();
  1138.         }
  1139.         return m_pRMBox;
  1140. }
  1141.  
  1142. //////////////////////////////////////////////////////////////////////////
  1143. void CObjManager::CheckForGarbage(CStatObj* pObject)
  1144. {
  1145.         if (m_bGarbageCollectionEnabled &&
  1146.             !pObject->m_bCheckGarbage)
  1147.         {
  1148.                 pObject->m_bCheckGarbage = true;
  1149.                 m_checkForGarbage.push_back(pObject);
  1150.         }
  1151. }
  1152.  
  1153. //////////////////////////////////////////////////////////////////////////
  1154. void CObjManager::UnregisterForGarbage(CStatObj* pObject)
  1155. {
  1156.         CRY_ASSERT(pObject);
  1157.  
  1158.         if (m_bGarbageCollectionEnabled &&
  1159.             pObject->m_bCheckGarbage)
  1160.         {
  1161.                 m_checkForGarbage.try_remove(pObject);
  1162.                 pObject->m_bCheckGarbage = false;
  1163.         }
  1164. }
  1165.  
  1166. //////////////////////////////////////////////////////////////////////////
  1167. bool CObjManager::AddOrCreatePersistentRenderObject(SRenderNodeTempData* pTempData, CRenderObject*& pRenderObject, const CLodValue* pLodValue, const SRenderingPassInfo& passInfo) const
  1168. {
  1169.         CRY_ASSERT(pRenderObject == nullptr);
  1170.  
  1171.         if (GetCVars()->e_PermanentRenderObjects && (pTempData || pRenderObject) && GetCVars()->e_DebugDraw == 0 && (!pLodValue || !pLodValue->DissolveRefA()))
  1172.         {
  1173.                 if (passInfo.IsRecursivePass() || (pTempData && (pTempData->userData.m_pFoliage || (pTempData->userData.pOwnerNode && (pTempData->userData.pOwnerNode->GetRndFlags() & ERF_SELECTED)))))
  1174.                 {
  1175.                         // Recursive and Debug passes do not support permanent render objects now...
  1176.                         pRenderObject = gEnv->pRenderer->EF_GetObject_Temp(passInfo.ThreadID());
  1177.                         return false;
  1178.                 }
  1179.  
  1180.                 if (pLodValue && pLodValue->LodA() == -1 && pLodValue->LodB() == -1)
  1181.                         return true;
  1182.  
  1183.                 if (pLodValue && pLodValue->LodA() == -1 && pLodValue->DissolveRefB() == 255)
  1184.                         return true;
  1185.  
  1186.                 if (pLodValue && pLodValue->LodB() == -1 && pLodValue->DissolveRefA() == 255)
  1187.                         return true;
  1188.  
  1189.                 int nLod = pLodValue ? CLAMP(0, pLodValue->LodA(), MAX_STATOBJ_LODS_NUM - 1) : 0;
  1190.  
  1191.                 uint32 passId = passInfo.IsShadowPass() ? 1 : 0;
  1192.                 uint32 passMask = 1 << passId;
  1193.  
  1194.                 // Do we have to create a new permanent render object?
  1195.                 if (pTempData->userData.arrPermanentRenderObjects[nLod] == nullptr)
  1196.                 {
  1197.                         // Object creation must be locked because CheckCreateRenderObject can be called on same node from different threads
  1198.                         WriteLock lock(pTempData->userData.permanentObjectCreateLock);
  1199.  
  1200.                         // Did another thread succeed in creating the object in the meantime?
  1201.                         if (pTempData->userData.arrPermanentRenderObjects[nLod] == nullptr)
  1202.                                 pTempData->userData.arrPermanentRenderObjects[nLod] = gEnv->pRenderer->EF_GetObject();
  1203.                 }
  1204.  
  1205.                 pRenderObject = pTempData->userData.arrPermanentRenderObjects[nLod];
  1206.                 passInfo.GetIRenderView()->AddPermanentObject(pRenderObject, passInfo);
  1207.  
  1208.                 // Has this object already been filled?
  1209.                 int previousMask = CryInterlockedExchangeOr(reinterpret_cast<volatile LONG*>(&pRenderObject->m_passReadyMask), passMask);
  1210.                 if (previousMask & passMask) // Object drawn once => fast path.
  1211.                 {
  1212.                         if (GetCVars()->e_BBoxes && pTempData && pTempData->userData.pOwnerNode)
  1213.                                 GetObjManager()->RenderObjectDebugInfo(pTempData->userData.pOwnerNode, pRenderObject->m_fDistance, passInfo);
  1214.  
  1215.                         return true;
  1216.                 }
  1217.  
  1218.                 // Permanent object needs to be filled first time,
  1219.                 if (pTempData->IsValid())
  1220.                         pTempData->userData.nStatObjLastModificationId = GetResourcesModificationChecksum(pTempData->userData.pOwnerNode);
  1221.  
  1222.                 return false;
  1223.         }
  1224.  
  1225.         pRenderObject = gEnv->pRenderer->EF_GetObject_Temp(passInfo.ThreadID());
  1226.  
  1227.         return false;
  1228. }
  1229.  
  1230. //////////////////////////////////////////////////////////////////////////
  1231. uint32 CObjManager::GetResourcesModificationChecksum(IRenderNode* pOwnerNode) const
  1232. {
  1233.         uint32 nModificationId = 1;
  1234.  
  1235.         if (CStatObj* pStatObj = (CStatObj*)pOwnerNode->GetEntityStatObj())
  1236.                 nModificationId += pStatObj->GetModificationId();
  1237.  
  1238.         if (CMatInfo* pMatInfo = (CMatInfo*)pOwnerNode->GetMaterial())
  1239.                 nModificationId += pMatInfo->GetModificationId();
  1240.  
  1241.         if (pOwnerNode->GetRenderNodeType() == eERType_TerrainSector)
  1242.                 nModificationId += ((CTerrainNode*)pOwnerNode)->GetMaterialsModificationId();
  1243.  
  1244.         return nModificationId;
  1245. }
  1246.  
downloadObjMan.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top