BVB Source Codes

CRYENGINE Show CharacterManager.cpp Source code

Return Download CRYENGINE: download CharacterManager.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "stdafx.h"
  4. #include "CharacterManager.h"
  5.  
  6. #include "CharacterInstance.h"
  7. #include "LoaderCHR.h"
  8. #include "LoaderCGA.h"
  9. #include "AnimationManager.h"
  10. #include "FacialAnimation/FaceAnimation.h"
  11. #include <CryGame/IGameFramework.h>
  12. #include <CrySystem/File/IResourceManager.h>
  13. #include "ParametricSampler.h"
  14. #include "AttachmentVCloth.h"
  15. #include "AttachmentMerger.h"
  16. #include "Serialization/SerializationCommon.h"
  17.  
  18. float g_YLine = 0.0f;
  19.  
  20. #define CDF_LEVEL_CACHE_PAK     "cdf.pak"
  21. #define CHR_LEVEL_CACHE_PAK     "chr.pak"
  22. #define CGA_LEVEL_CACHE_PAK     "cga.pak"
  23.  
  24. #define DBA_UNLOAD_MAX_DELTA_MS 2000
  25.  
  26. #define INVALID_CDF_ID          ~0
  27. /*
  28.    CharacterManager
  29.  */
  30.  
  31. bool CharacterManager::s_bPaused = false;
  32. uint32 CharacterManager::s_renderFrameIdLocal = 0;
  33.  
  34. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  35. // CharacterManager
  36. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  37.  
  38. CharacterManager::CharacterManager()
  39. {
  40.         m_AllowStartOfAnimation = 1;
  41.         m_arrFrameTimes.resize(200);
  42.         for (uint32 i = 0; i < 200; i++)
  43.                 m_arrFrameTimes[i] = 0.014f;
  44.  
  45.         m_pFacialAnimation = new CFacialAnimation();
  46.         m_nUpdateCounter = 0;
  47.         m_InitializedByIMG = 0;
  48.         m_StartGAH_Iterator = 0;
  49.  
  50.         m_pStreamingListener = NULL;
  51.  
  52.         m_arrModelCacheSKEL.reserve(100);
  53.         m_arrModelCacheSKIN.reserve(100);
  54.         g_SkeletonUpdates = 0;
  55.         g_AnimationUpdates = 0;
  56.         m_nFrameSyncTicks = 0;
  57.         m_nFrameTicks = 0;
  58.         m_nActiveCharactersLastFrame = 0;
  59.  
  60.         UpdateDatabaseUnloadTimeStamp();
  61.         m_arrCacheForCDF.reserve(1024);
  62.  
  63.         memset(m_nStreamUpdateRoundId, 0, sizeof(m_nStreamUpdateRoundId));
  64. }
  65.  
  66. void CharacterManager::PostInit()
  67. {
  68.         if (g_pISystem == 0)
  69.                 CryFatalError("CryAnimation: ISystem not initialized");
  70.  
  71.         PREFAST_ASSUME(g_pISystem);
  72.         g_pIRenderer = g_pISystem->GetIRenderer();
  73.  
  74.         g_pIPhysicalWorld = g_pISystem->GetIPhysicalWorld();
  75.         if (g_pIPhysicalWorld == 0)
  76.                 CryFatalError("CryAnimation: failed to initialize pIPhysicalWorld");
  77.  
  78.         g_pI3DEngine = g_pISystem->GetI3DEngine();
  79.         if (g_pI3DEngine == 0)
  80.                 CryFatalError("CryAnimation: failed to initialize pI3DEngine");
  81. }
  82.  
  83. CharacterManager::~CharacterManager()
  84. {
  85.         uint32 numModels = m_arrModelCacheSKEL.size();
  86.         if (numModels)
  87.         {
  88.                 g_pILog->LogToFile("*ERROR* CharacterManager: %" PRISIZE_T " body instances still not deleted. Forcing deletion (though some instances may still refer to them)", m_arrModelCacheSKEL.size());
  89.                 CleanupModelCache(true);
  90.         }
  91.  
  92.         delete m_pFacialAnimation;
  93.  
  94.         //g_DeleteInterfaces();
  95. }
  96.  
  97. //////////////////////////////////////////////////////////////////////////
  98. void CharacterManager::PreloadLevelModels()
  99. {
  100.         LOADING_TIME_PROFILE_SECTION;
  101.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Preload Characters");
  102.  
  103.         //bool bCdfCacheExist = GetISystem()->GetIResourceManager()->LoadLevelCachePak( CDF_LEVEL_CACHE_PAK,"" ); // Keep it open until level end.
  104.  
  105.         PreloadModelsCHR();
  106.  
  107.         PreloadModelsCGA();
  108.  
  109.         PreloadModelsCDF();
  110.  
  111.         if (Console::GetInst().ca_PreloadAllCAFs)
  112.         {
  113.                 //This is a blocking call to load all global animation headers rather than waiting for them to stream in
  114.                 //Alternative is to use the DBA system in asset pipeline
  115.                 const int numGlobalCAF = GetAnimationManager().m_arrGlobalCAF.size();
  116.  
  117.                 for (int i = 0; i < numGlobalCAF; ++i)
  118.                 {
  119.                         GlobalAnimationHeaderCAF& rCAF = GetAnimationManager().m_arrGlobalCAF[i];
  120.                         if (rCAF.IsAssetLoaded() == 0 && rCAF.IsAssetRequested() == 0)
  121.                                 rCAF.LoadCAF();
  122.                 }
  123.         }
  124. }
  125.  
  126. //////////////////////////////////////////////////////////////////////////
  127. void CharacterManager::PreloadModelsCHR()
  128. {
  129.         LOADING_TIME_PROFILE_SECTION;
  130.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Preload CHR");
  131.  
  132.         CryLog("===== Preloading Characters ====");
  133.  
  134.         CTimeValue startTime = gEnv->pTimer->GetAsyncTime();
  135.  
  136.         //bool bChrCacheExist = GetISystem()->GetIResourceManager()->LoadLevelCachePak( CHR_LEVEL_CACHE_PAK,"" );
  137.  
  138.         IResourceList* pResList = GetISystem()->GetIResourceManager()->GetLevelResourceList();
  139.  
  140.         // Construct streamer object
  141.         //CLevelStatObjLoader cgfStreamer;
  142.  
  143.         int nChrCounter = 0;
  144.         int nInLevelCacheCount = 0;
  145.  
  146.         // Request objects loading from Streaming System.
  147.         CryPathString filename;
  148.         const char* sFilenameInResource = pResList->GetFirst();
  149.         while (sFilenameInResource)
  150.         {
  151.                 const char* fileExt = PathUtil::GetExt(sFilenameInResource);
  152.                 uint32 IsSKIN = stricmp(fileExt, CRY_SKIN_FILE_EXT) == 0;
  153.                 uint32 IsSKEL = stricmp(fileExt, CRY_SKEL_FILE_EXT) == 0;
  154.  
  155.                 if (IsSKEL)
  156.                 {
  157.                         const char* sLodName = strstr(sFilenameInResource, "_lod");
  158.                         if (sLodName && (sLodName[4] >= '0' && sLodName[4] <= '9'))
  159.                         {
  160.                                 // Ignore Lod files.
  161.                                 sFilenameInResource = pResList->GetNext();
  162.                                 continue;
  163.                         }
  164.                         filename = sFilenameInResource;
  165.                         uint32 nFileOnDisk = gEnv->pCryPak->IsFileExist(filename);
  166.                         if (nFileOnDisk)
  167.                         {
  168.                                 CDefaultSkeleton* pSkel = FetchModelSKEL(filename.c_str(), 0);
  169.                                 if (pSkel)
  170.                                         pSkel->SetKeepInMemory(true), nChrCounter++;
  171.                         }
  172.                 }
  173.  
  174.                 if (IsSKIN)  //we don't want ".chrparams" in the list
  175.                 {
  176.                         const char* sLodName = strstr(sFilenameInResource, "_lod");
  177.                         if (sLodName && (sLodName[4] >= '0' && sLodName[4] <= '9'))
  178.                         {
  179.                                 // Ignore Lod files.
  180.                                 sFilenameInResource = pResList->GetNext();
  181.                                 continue;
  182.                         }
  183.                         filename = sFilenameInResource;
  184.                         uint32 nFileOnDisk = gEnv->pCryPak->IsFileExist(filename);
  185.                         assert(nFileOnDisk);
  186.                         if (nFileOnDisk)
  187.                         {
  188.                                 CSkin* pSkin = FetchModelSKIN(filename.c_str(), 0);
  189.                                 if (pSkin)
  190.                                         pSkin->SetKeepInMemory(true), nChrCounter++;
  191.                         }
  192.                 }
  193.  
  194.                 sFilenameInResource = pResList->GetNext();
  195.                 SLICE_AND_SLEEP();
  196.         }
  197.  
  198.         //all reference must be 0 after loading
  199.         uint32 numSKELs = m_arrModelCacheSKEL.size();
  200.         for (uint32 i = 0; i < numSKELs; i++)
  201.         {
  202.                 uint32 numRefs = m_arrModelCacheSKEL[i].m_pDefaultSkeleton->GetRefCounter();
  203.                 if (numRefs)
  204.                         CryFatalError("SKEL NumRefs: %d", numRefs);
  205.         }
  206.         uint32 numSKINs = m_arrModelCacheSKIN.size();
  207.         for (uint32 i = 0; i < numSKINs; i++)
  208.         {
  209.                 uint32 numRefs = m_arrModelCacheSKIN[i].m_pDefaultSkinning->GetRefCounter();
  210.                 if (numRefs)
  211.                         CryFatalError("SKIN NumRefs: %d", numRefs);
  212.         }
  213.  
  214.         CTimeValue endTime = gEnv->pTimer->GetAsyncTime();
  215.  
  216.         float dt = (endTime - startTime).GetSeconds();
  217.  
  218.         CryLog("===== Finished Preloading %d Characters in %.2f seconds ====", nChrCounter, dt);
  219.  
  220.         //GetISystem()->GetIResourceManager()->UnloadLevelCachePak( CHR_LEVEL_CACHE_PAK );
  221. }
  222.  
  223. void CharacterManager::PreloadModelsCGA()
  224. {
  225.         LOADING_TIME_PROFILE_SECTION;
  226.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Preload CGA");
  227.  
  228.         CryLog("===== Preloading CGAs ====");
  229.  
  230.         CTimeValue startTime = gEnv->pTimer->GetAsyncTime();
  231.  
  232.         //bool bCGACacheExist = false;
  233.  
  234.         bool bCgfCacheExist = false;
  235.         static ICVar* pCVar_e_StreamCgf = gEnv->pConsole->GetCVar("e_StreamCgf");
  236.         if (pCVar_e_StreamCgf && pCVar_e_StreamCgf->GetIVal() != 0)
  237.         {
  238.                 // Only when streaming enable use no-mesh cga pak.
  239.                 //bCGACacheExist = GetISystem()->GetIResourceManager()->LoadLevelCachePak( CGA_LEVEL_CACHE_PAK,"" );
  240.         }
  241.  
  242.         int nChrCounter = 0;
  243.         IResourceList* pResList = GetISystem()->GetIResourceManager()->GetLevelResourceList();
  244.  
  245.         CryCGALoader CGALoader;
  246.  
  247.         // Request objects loading from Streaming System.
  248.         CryPathString filename;
  249.         const char* sFilenameInResource = pResList->GetFirst();
  250.         const uint32 nLoadingFlags = 0;
  251.         while (sFilenameInResource)
  252.         {
  253.                 if (strstr(sFilenameInResource, ".cga"))
  254.                 {
  255.                         const char* sLodName = strstr(sFilenameInResource, "_lod");
  256.                         if (sLodName && (sLodName[4] >= '0' && sLodName[4] <= '9'))
  257.                         {
  258.                                 // Ignore Lod files.
  259.                                 sFilenameInResource = pResList->GetNext();
  260.                                 continue;
  261.                         }
  262.  
  263.                         filename = sFilenameInResource;
  264.                         uint32 nFileOnDisk = gEnv->pCryPak->IsFileExist(filename);
  265.                         assert(nFileOnDisk);
  266.                         CDefaultSkeleton* pSkelTemp = 0;    //temp-pointer to access the refcounter, without calling the destructor
  267.                         if (nFileOnDisk)
  268.                         {
  269.                                 LoadAnimationImageFile("animations/animations.img", "animations/DirectionalBlends.img");
  270.                                 CGALoader.Reset();
  271.                                 CDefaultSkeleton* pDefaultSkeleton = CGALoader.LoadNewCGA(filename, this, nLoadingFlags);
  272.                                 if (pDefaultSkeleton)
  273.                                 {
  274.                                         pDefaultSkeleton->SetKeepInMemory(true);
  275.                                         RegisterModelSKEL(pDefaultSkeleton, nLoadingFlags);
  276.                                         nChrCounter++;
  277.                                 }
  278.                         }
  279.                 }
  280.                 sFilenameInResource = pResList->GetNext();
  281.  
  282.                 SLICE_AND_SLEEP();
  283.         }
  284.  
  285.         //all reference must be 0 after loading
  286.         uint32 numSKELs = m_arrModelCacheSKEL.size();
  287.         for (uint32 i = 0; i < numSKELs; i++)
  288.         {
  289.                 uint32 numRefs = m_arrModelCacheSKEL[i].m_pDefaultSkeleton->GetRefCounter();
  290.                 if (numRefs)
  291.                         CryFatalError("SKEL NumRefs: %d", numRefs);
  292.         }
  293.  
  294.         //GetISystem()->GetIResourceManager()->UnloadLevelCachePak( CGA_LEVEL_CACHE_PAK );
  295.  
  296.         CTimeValue endTime = gEnv->pTimer->GetAsyncTime();
  297.  
  298.         float dt = (endTime - startTime).GetSeconds();
  299.         CryLog("===== Finished Preloading %d CGAs in %.2f seconds ====", nChrCounter, dt);
  300. }
  301.  
  302. //////////////////////////////////////////////////////////////////////////
  303. void CharacterManager::PreloadModelsCDF()
  304. {
  305.         LOADING_TIME_PROFILE_SECTION;
  306.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Preload CDF");
  307.  
  308.         CryLog("===== Preloading CDFs ====");
  309.  
  310.         CTimeValue startTime = gEnv->pTimer->GetAsyncTime();
  311.  
  312.         int nCounter = 0;
  313.  
  314.         IResourceList* pResList = GetISystem()->GetIResourceManager()->GetLevelResourceList();
  315.  
  316.         // Request objects loading from Streaming System.
  317.         CryPathString filename;
  318.         const char* sFilenameInResource = pResList->GetFirst();
  319.         while (sFilenameInResource)
  320.         {
  321.                 if (strstr(sFilenameInResource, ".cdf"))
  322.                 {
  323.                         filename = sFilenameInResource;
  324.  
  325.                         if (gEnv->pCryPak->IsFileExist(filename))
  326.                         {
  327.                                 const uint32 nCdfIndex = LoadCDF(filename);
  328.                                 if (nCdfIndex != INVALID_CDF_ID)
  329.                                 {
  330.                                         m_arrCacheForCDF[nCdfIndex].AddRef(); // Keep reference to it.
  331.                                         nCounter++;
  332.                                 }
  333.                         }
  334.                 }
  335.                 sFilenameInResource = pResList->GetNext();
  336.  
  337.                 SLICE_AND_SLEEP();
  338.         }
  339.  
  340.         CTimeValue endTime = gEnv->pTimer->GetAsyncTime();
  341.  
  342.         float dt = (endTime - startTime).GetSeconds();
  343.         CryLog("===== Finished Preloading %d CDFs in %.2f seconds ====", nCounter, dt);
  344. }
  345.  
  346. //////////////////////////////////////////////////////////////////////////
  347. // Loads a cgf and the corresponding caf file and creates an animated object,
  348. // or returns an existing object.
  349. ICharacterInstance* CharacterManager::CreateInstance(const char* szFilePath, uint32 nLoadingFlags)
  350. {
  351.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Characters");
  352.         if (szFilePath == 0)
  353.                 return (NULL);                                                      // to prevent a crash in the frequent case the designers will mess
  354.  
  355.         stack_string strFilePath = szFilePath;
  356.         PathUtil::UnifyFilePath(strFilePath);
  357.  
  358. #if !CRY_PLATFORM_DESKTOP
  359.         //there is no char-edit on consoles
  360.         nLoadingFlags = nLoadingFlags & (CA_CharEditModel ^ -1);
  361. #endif
  362.  
  363.         const char* fileExt = PathUtil::GetExt(strFilePath.c_str());
  364.         uint32 isSKIN = stricmp(fileExt, CRY_SKIN_FILE_EXT) == 0;
  365.         uint32 isSKEL = stricmp(fileExt, CRY_SKEL_FILE_EXT) == 0;
  366.         uint32 isCGA = stricmp(fileExt, "cga") == 0;
  367.         uint32 isCDF = stricmp(fileExt, "cdf") == 0;
  368.  
  369. #ifdef EDITOR_PCDEBUGCODE
  370.         if (isSKIN)
  371.                 return CreateSKELInstance(strFilePath.c_str(), nLoadingFlags);       //Load SKIN and install it as a SKEL file (this is only needed in CharEdit-Mode to preview the model)
  372. #endif
  373.  
  374.         if (isSKEL)
  375.                 return CreateSKELInstance(strFilePath.c_str(), nLoadingFlags);       //Loading SKEL file.
  376.  
  377.         if (isCGA)
  378.                 return CreateCGAInstance(strFilePath.c_str(), nLoadingFlags);        //Loading CGA file.
  379.  
  380.         if (isCDF)
  381.                 return LoadCharacterDefinition(strFilePath.c_str(), nLoadingFlags);  //Loading CDF file.
  382.  
  383.         g_pILog->LogError("CryAnimation: no valid character file-format a SKEL-Instance: %s", strFilePath.c_str());
  384.         return 0;                                                             //if it ends here, then we have no valid file-format
  385. }
  386.  
  387. ICharacterInstance* CharacterManager::CreateSKELInstance(const char* strFilePath, uint32 nLoadingFlags)
  388. {
  389.         LOADING_TIME_PROFILE_SECTION(g_pISystem);
  390.         CDefaultSkeleton* pModelSKEL = CheckIfModelSKELLoaded(strFilePath, nLoadingFlags);
  391.         if (pModelSKEL == 0)
  392.         {
  393.                 pModelSKEL = FetchModelSKEL(strFilePath, nLoadingFlags);               //SKIN not in memory, so load it
  394.                 if (pModelSKEL == 0)
  395.                         return NULL;                                                      // the model has not been loaded
  396.         }
  397.         else
  398.         {
  399.                 uint32 isPrevMode = nLoadingFlags & CA_PreviewMode;
  400.                 if (isPrevMode == 0)
  401.                 {
  402.                         uint32 numAnims = pModelSKEL->m_pAnimationSet->GetAnimationCount();
  403.                         if (numAnims == 0)
  404.                         {
  405.                                 const char* szExt = PathUtil::GetExt(strFilePath);
  406.                                 stack_string strGeomFileNameNoExt;
  407.                                 strGeomFileNameNoExt.assign(strFilePath, *szExt ? szExt - 1 : szExt);
  408.                                 stack_string paramFileName = strGeomFileNameNoExt + "." + CRY_CHARACTER_PARAM_FILE_EXT;
  409.                                 pModelSKEL->LoadCHRPARAMS(paramFileName);
  410.                         }
  411.                 }
  412.         }
  413.         return new CCharInstance(strFilePath, pModelSKEL);
  414. }
  415.  
  416. //////////////////////////////////////////////////////////////////////////
  417.  
  418. ISkin* CharacterManager::LoadModelSKIN(const char* szFilePath, uint32 nLoadingFlags)
  419. {
  420.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Characters");
  421.         if (szFilePath == 0)
  422.                 return 0;                                                                           //to prevent a crash in the frequent case the designers will mess bad filenames
  423.  
  424. #if !CRY_PLATFORM_DESKTOP
  425.         //there is no char-edit on consoles
  426.         nLoadingFlags = nLoadingFlags & (CA_CharEditModel ^ -1);
  427. #endif
  428.  
  429.         stack_string strFilePath = szFilePath;
  430.         PathUtil::UnifyFilePath(strFilePath);
  431.  
  432.         const char* fileExt = PathUtil::GetExt(strFilePath.c_str());
  433.         uint32 isSKIN = stricmp(fileExt, CRY_SKIN_FILE_EXT) == 0;
  434.         if (isSKIN)
  435.         {
  436.                 LOADING_TIME_PROFILE_SECTION(g_pISystem);
  437.                 CSkin* pModelSKIN = FetchModelSKIN(strFilePath.c_str(), nLoadingFlags);
  438.                 return pModelSKIN;
  439.         }
  440.  
  441.         g_pILog->LogError("CryAnimation: no valid character file-format to create a skin-attachment: %s", strFilePath.c_str());
  442.         return 0;                                                                             //if it ends here, then we have no valid file-format
  443. }
  444.  
  445. //////////////////////////////////////////////////////////////////////////
  446.  
  447. IDefaultSkeleton* CharacterManager::LoadModelSKEL(const char* szFilePath, uint32 nLoadingFlags)
  448. {
  449.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Characters");
  450.         if (szFilePath == 0)
  451.                 return 0;                                                                           //to prevent a crash in the frequent case the designers will mess bad filenames
  452.  
  453. #if !CRY_PLATFORM_DESKTOP
  454.         //there is no char-edit on consoles
  455.         nLoadingFlags = nLoadingFlags & (CA_CharEditModel ^ -1);
  456. #endif
  457.  
  458.         stack_string strFilePath = szFilePath;
  459.         PathUtil::UnifyFilePath(strFilePath);
  460.  
  461.         const char* fileExt = PathUtil::GetExt(strFilePath.c_str());
  462.         uint32 isSKEL = stricmp(fileExt, CRY_SKEL_FILE_EXT) == 0;
  463.         if (isSKEL)
  464.         {
  465.                 LOADING_TIME_PROFILE_SECTION(g_pISystem);
  466.                 CDefaultSkeleton* pModelSKEL = FetchModelSKEL(strFilePath.c_str(), nLoadingFlags);  //SKEL not in memory, so load it
  467.                 return pModelSKEL;                                                                  //SKIN not in memory, so load it
  468.         }
  469.  
  470.         g_pILog->LogError("CryAnimation: no valid character file-format to create a skin-attachment: %s", strFilePath.c_str());
  471.         return 0;                                                                             //if it ends here, then we have no valid file-format
  472. }
  473.  
  474. //////////////////////////////////////////////////////////////////////////
  475. CDefaultSkeleton* CharacterManager::CheckIfModelSKELLoaded(const string& strFilePath, uint32 nLoadingFlags)
  476. {
  477.         if ((nLoadingFlags & CA_CharEditModel) == 0)
  478.         {
  479.                 uint32 numModels = m_arrModelCacheSKEL.size();
  480.                 for (uint32 m = 0; m < numModels; m++)
  481.                 {
  482.                         const char* strFilePath1 = strFilePath.c_str();
  483.                         const char* strFilePath2 = m_arrModelCacheSKEL[m].m_pDefaultSkeleton->GetModelFilePath();
  484.                         bool IsIdentical = stricmp(strFilePath1, strFilePath2) == 0;
  485.                         if (IsIdentical)
  486.                                 return m_arrModelCacheSKEL[m].m_pDefaultSkeleton;                               //model already loaded
  487.                 }
  488.         }
  489.         else
  490.         {
  491. #ifdef EDITOR_PCDEBUGCODE
  492.                 uint32 numModels = m_arrModelCacheSKEL_CharEdit.size();
  493.                 for (uint32 m = 0; m < numModels; m++)
  494.                 {
  495.                         const char* strFilePath1 = strFilePath.c_str();
  496.                         const char* strFilePath2 = m_arrModelCacheSKEL_CharEdit[m].m_pDefaultSkeleton->GetModelFilePath();
  497.                         bool IsIdentical = stricmp(strFilePath1, strFilePath2) == 0;
  498.                         if (IsIdentical)
  499.                                 return m_arrModelCacheSKEL_CharEdit[m].m_pDefaultSkeleton;                      //model already loaded
  500.                 }
  501. #endif
  502.         }
  503.         return 0;
  504.  
  505. }
  506.  
  507. CDefaultSkeleton* CharacterManager::CheckIfModelExtSKELCreated(const uint64 nCRC64, uint32 nLoadingFlags)
  508. {
  509.         if ((nLoadingFlags & CA_CharEditModel) == 0)
  510.         {
  511.                 uint32 numModels = m_arrModelCacheSKEL.size();
  512.                 for (uint32 m = 0; m < numModels; m++)
  513.                 {
  514.                         uint64 crc64 = m_arrModelCacheSKEL[m].m_pDefaultSkeleton->GetModelFilePathCRC64();
  515.                         if (nCRC64 == crc64)
  516.                                 return m_arrModelCacheSKEL[m].m_pDefaultSkeleton;                               //model already loaded
  517.                 }
  518.         }
  519.         else
  520.         {
  521. #ifdef EDITOR_PCDEBUGCODE
  522.                 uint32 numModels = m_arrModelCacheSKEL_CharEdit.size();
  523.                 for (uint32 m = 0; m < numModels; m++)
  524.                 {
  525.                         uint64 crc64 = m_arrModelCacheSKEL_CharEdit[m].m_pDefaultSkeleton->GetModelFilePathCRC64();
  526.                         if (nCRC64 == crc64)
  527.                                 return m_arrModelCacheSKEL_CharEdit[m].m_pDefaultSkeleton;                      //model already loaded
  528.                 }
  529. #endif
  530.         }
  531.         return 0;
  532. }
  533.  
  534. //////////////////////////////////////////////////////////////////////////
  535. CSkin* CharacterManager::CheckIfModelSKINLoaded(const string& strFilePath, uint32 nLoadingFlags)
  536. {
  537.         if ((nLoadingFlags & CA_CharEditModel) == 0)
  538.         {
  539.                 uint32 numModels = m_arrModelCacheSKIN.size();
  540.                 for (uint32 m = 0; m < numModels; m++)
  541.                 {
  542.                         const char* strBodyFilePath = m_arrModelCacheSKIN[m].m_pDefaultSkinning->GetModelFilePath();
  543.                         if (strFilePath.compareNoCase(strBodyFilePath) == 0)
  544.                                 return m_arrModelCacheSKIN[m].m_pDefaultSkinning;                               //model already loaded
  545.                 }
  546.         }
  547.         else
  548.         {
  549. #ifdef EDITOR_PCDEBUGCODE
  550.                 uint32 numModels = m_arrModelCacheSKIN_CharEdit.size();
  551.                 for (uint32 m = 0; m < numModels; m++)
  552.                 {
  553.                         const char* strBodyFilePath = m_arrModelCacheSKIN_CharEdit[m].m_pDefaultSkinning->GetModelFilePath();
  554.                         if (strFilePath.compareNoCase(strBodyFilePath) == 0)
  555.                                 return m_arrModelCacheSKIN_CharEdit[m].m_pDefaultSkinning;                      //model already loaded
  556.                 }
  557. #endif
  558.         }
  559.         return 0;
  560.  
  561. }
  562.  
  563. //////////////////////////////////////////////////////////////////////////
  564. CDefaultSkinningReferences* CharacterManager::GetDefaultSkinningReferences(CSkin* pDefaultSkinning)
  565. {
  566.         if ((pDefaultSkinning->m_nLoadingFlags & CA_CharEditModel) == 0)
  567.         {
  568.                 uint32 numModels = m_arrModelCacheSKIN.size();
  569.                 for (uint32 m = 0; m < numModels; m++)
  570.                 {
  571.                         if (m_arrModelCacheSKIN[m].m_pDefaultSkinning == pDefaultSkinning)
  572.                                 return &m_arrModelCacheSKIN[m];
  573.                 }
  574.         }
  575.         else
  576.         {
  577. #ifdef EDITOR_PCDEBUGCODE
  578.                 uint32 numModels = m_arrModelCacheSKIN_CharEdit.size();
  579.                 for (uint32 m = 0; m < numModels; m++)
  580.                 {
  581.                         if (m_arrModelCacheSKIN_CharEdit[m].m_pDefaultSkinning == pDefaultSkinning)
  582.                                 return &m_arrModelCacheSKIN_CharEdit[m];
  583.                 }
  584. #endif
  585.         }
  586.         return 0;
  587.  
  588. }
  589.  
  590. //////////////////////////////////////////////////////////////////////////
  591. // Finds a cached or creates a new CDefaultSkeleton instance and returns it
  592. // returns NULL if the construction failed
  593. CDefaultSkeleton* CharacterManager::FetchModelSKEL(const char* szFilePath, uint32 nLoadingFlags)
  594. {
  595.         CDefaultSkeleton* pModelSKEL = CheckIfModelSKELLoaded(szFilePath, nLoadingFlags);
  596.         if (pModelSKEL)
  597.                 return pModelSKEL;
  598.  
  599.         pModelSKEL = new CDefaultSkeleton(szFilePath, CHR);
  600.         if (pModelSKEL)
  601.         {
  602.                 pModelSKEL->m_pAnimationSet = new CAnimationSet(szFilePath);
  603.  
  604.                 LoadAnimationImageFile("animations/animations.img", "animations/DirectionalBlends.img");
  605.                 bool IsLoaded = pModelSKEL->LoadNewSKEL(szFilePath, nLoadingFlags);
  606.                 if (IsLoaded == 0)
  607.                 {
  608.                         delete pModelSKEL;
  609.                         return 0; //loading error
  610.                 }
  611.                 RegisterModelSKEL(pModelSKEL, nLoadingFlags);
  612.                 return pModelSKEL;
  613.         }
  614.         return 0;     //some error
  615. }
  616.  
  617. //////////////////////////////////////////////////////////////////////////
  618.  
  619. CDefaultSkeleton* CharacterManager::FetchModelSKELForGCA(const char* szFilePath, uint32 nLoadingFlags)
  620. {
  621.         CDefaultSkeleton* pModelSKEL = CheckIfModelSKELLoaded(szFilePath, nLoadingFlags);
  622.         if (pModelSKEL == 0)
  623.         {
  624.                 LoadAnimationImageFile("animations/animations.img", "animations/DirectionalBlends.img");
  625.                 CryCGALoader CGALoader;
  626.                 pModelSKEL = CGALoader.LoadNewCGA(szFilePath, this, nLoadingFlags);
  627.                 if (pModelSKEL)
  628.                         RegisterModelSKEL(pModelSKEL, nLoadingFlags);
  629.         }
  630.         return pModelSKEL;
  631. }
  632.  
  633. //////////////////////////////////////////////////////////////////////////
  634.  
  635. CSkin* CharacterManager::FetchModelSKIN(const char* szFilePath, uint32 nLoadingFlags)
  636. {
  637.         CSkin* pModelSKIN = CheckIfModelSKINLoaded(szFilePath, nLoadingFlags);
  638.         if (pModelSKIN)
  639.                 return pModelSKIN;
  640.  
  641.         pModelSKIN = new CSkin(szFilePath, nLoadingFlags);    // Wrap the model in a smart pointer to guard against early-exit memory leaks due to a bad asset
  642.         if (pModelSKIN)
  643.         {
  644.                 bool IsLoaded = pModelSKIN->LoadNewSKIN(szFilePath, nLoadingFlags);
  645.                 if (IsLoaded == 0)
  646.                 {
  647.                         delete pModelSKIN;
  648.                         return 0;                                      //loading error
  649.                 }
  650.                 RegisterModelSKIN(pModelSKIN, nLoadingFlags);
  651.                 return pModelSKIN;
  652.         }
  653.         return 0;                                          //some error
  654. }
  655.  
  656. bool CharacterManager::LoadAndLockResources(const char* szFilePath, uint32 nLoadingFlags)
  657. {
  658.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Characters");
  659.         if (szFilePath == 0)
  660.                 return false;
  661.  
  662.         //Note: This initialization is copied from CreateInstance( ), it could be that this pointers haven't been initialized yet at this point?
  663.         g_pIRenderer = g_pISystem->GetIRenderer();
  664.         g_pIPhysicalWorld = g_pISystem->GetIPhysicalWorld();
  665.         g_pI3DEngine = g_pISystem->GetI3DEngine();
  666.  
  667.         stack_string strFilePath = szFilePath;
  668.         PathUtil::UnifyFilePath(strFilePath);
  669.         const char* strFileExt = PathUtil::GetExt(strFilePath.c_str());
  670.  
  671.         const bool isCHR = stricmp(strFileExt, CRY_SKEL_FILE_EXT) == 0;
  672.         if (isCHR)
  673.         {
  674.                 CDefaultSkeleton* pModelSKEL = FetchModelSKEL(strFilePath, nLoadingFlags);
  675.                 if (pModelSKEL)
  676.                 {
  677.                         pModelSKEL->SetKeepInMemory(true);
  678.                         return true;
  679.                 }
  680.                 return false;                                                         //fail
  681.         }
  682.  
  683.         const bool isCGA = stricmp(strFileExt, CRY_ANIM_GEOMETRY_FILE_EXT) == 0;
  684.         if (isCGA)
  685.         {
  686.                 CDefaultSkeleton* pModelSKEL = FetchModelSKELForGCA(strFilePath, nLoadingFlags);
  687.                 if (pModelSKEL)
  688.                 {
  689.                         pModelSKEL->SetKeepInMemory(true);
  690.                         return true;
  691.                 }
  692.                 return false;                                                         //fail
  693.         }
  694.  
  695.         const bool isSKIN = stricmp(strFileExt, CRY_SKIN_FILE_EXT) == 0;
  696.         if (isSKIN)
  697.         {
  698.                 CSkin* pModelSKIN = FetchModelSKIN(strFilePath, nLoadingFlags);
  699.                 if (pModelSKIN)
  700.                 {
  701.                         pModelSKIN->SetKeepInMemory(true);
  702.                         return true;
  703.                 }
  704.                 return false;                                                         //fail
  705.         }
  706.  
  707.         const bool isCDF = stricmp(strFileExt, CRY_CHARACTER_DEFINITION_FILE_EXT) == 0;
  708.         if (isCDF)
  709.         {
  710.                 int32 cdfId = GetOrLoadCDFId(strFilePath);
  711.                 if (cdfId == INVALID_CDF_ID)
  712.                         return false;                                                       //fail
  713.  
  714.                 m_arrCacheForCDF[cdfId].m_nKeepInMemory = true;                         //always lock in memory
  715.                 const char* strBaseModelFilePath = m_arrCacheForCDF[cdfId].m_strBaseModelFilePath.c_str();
  716.                 CDefaultSkeleton* pBaseModelSKEL = FetchModelSKEL(strBaseModelFilePath, nLoadingFlags);
  717.                 if (pBaseModelSKEL)
  718.                 {
  719.                         pBaseModelSKEL->SetKeepInMemory(true);
  720.                         bool bKeep = false;
  721.                         int nKeepInMemory = m_arrCacheForCDF[cdfId].m_nKeepModelsInMemory;  //by default we keep all model-headers in memory
  722.                         if (nKeepInMemory)
  723.                                 bKeep = true;
  724.  
  725.                         uint32 numAttachments = m_arrCacheForCDF[cdfId].m_arrAttachments.size();
  726.                         for (uint32 a = 0; a < numAttachments; a++)
  727.                         {
  728.                                 const char* strAttFilePath = m_arrCacheForCDF[cdfId].m_arrAttachments[a].m_strBindingPath.c_str();
  729.                                 const char* strAttFileExt = PathUtil::GetExt(strAttFilePath);
  730.                                 const bool isAttSKEL = stricmp(strAttFileExt, CRY_SKEL_FILE_EXT) == 0;
  731.                                 if (isAttSKEL)
  732.                                 {
  733.                                         CDefaultSkeleton* pModelSKEL = FetchModelSKEL(strAttFilePath, nLoadingFlags);
  734.                                         if (pModelSKEL)
  735.                                                 pModelSKEL->SetKeepInMemory(bKeep);
  736.                                 }
  737.  
  738.                                 const bool isAttSKIN = stricmp(strAttFileExt, CRY_SKIN_FILE_EXT) == 0;
  739.                                 if (isAttSKIN)
  740.                                 {
  741.                                         CSkin* pModelSKIN = FetchModelSKIN(strAttFilePath, nLoadingFlags);
  742.                                         if (pModelSKIN)
  743.                                                 pModelSKIN->SetKeepInMemory(bKeep);
  744.                                 }
  745.                         }
  746.  
  747.                         return true; //success
  748.                 }
  749.         }
  750.  
  751.         return false;
  752. }
  753.  
  754. void CharacterManager::StreamKeepCharacterResourcesResident(const char* szFilePath, int nLod, bool bKeep, bool bUrgent)
  755. {
  756.         const char* fileExt = PathUtil::GetExt(szFilePath);
  757.  
  758.         int const nRefAdj = bKeep ? 1 : -1;
  759.  
  760.         const bool isSKIN = stricmp(fileExt, CRY_SKIN_FILE_EXT) == 0;
  761.         if (isSKIN)
  762.         {
  763.                 CSkin* pSkin = CheckIfModelSKINLoaded(szFilePath, 0);
  764.                 if (pSkin != NULL)
  765.                 {
  766.                         if (!pSkin->m_arrModelMeshes.empty())
  767.                         {
  768.                                 int nSkinLod = clamp_tpl(nLod, 0, pSkin->m_arrModelMeshes.size() - 1);
  769.                                 MeshStreamInfo& msi = pSkin->m_arrModelMeshes[nSkinLod].m_stream;
  770.  
  771.                                 msi.nKeepResidentRefs += nRefAdj;
  772.                                 msi.bIsUrgent = msi.bIsUrgent || bUrgent;
  773.                         }
  774.                 }
  775.                 return;
  776.         }
  777.  
  778.         const bool isSKEL = stricmp(fileExt, CRY_SKEL_FILE_EXT) == 0;
  779.         const bool isCGA = stricmp(fileExt, CRY_ANIM_GEOMETRY_FILE_EXT) == 0;
  780.         if (isSKEL || isCGA)
  781.         {
  782.                 if (CDefaultSkeleton* pSkeleton = CheckIfModelSKELLoaded(szFilePath, 0))
  783.                 {
  784.                         if (CModelMesh* pModelMesh = pSkeleton->GetModelMesh())
  785.                         {
  786.                                 MeshStreamInfo& msi = pModelMesh->m_stream;
  787.                                 msi.nKeepResidentRefs += nRefAdj;
  788.                                 msi.bIsUrgent = msi.bIsUrgent || bUrgent;
  789.                         }
  790.                 }
  791.                 return;
  792.         }
  793.  
  794.         const bool isCDF = stricmp(fileExt, CRY_CHARACTER_DEFINITION_FILE_EXT) == 0;
  795.         if (isCDF)
  796.         {
  797.                 StreamKeepCDFResident(szFilePath, nLod, nRefAdj, bUrgent);
  798.                 return;
  799.         }
  800. }
  801.  
  802. bool CharacterManager::StreamHasCharacterResources(const char* szFilePath, int nLod)
  803. {
  804.         const char* fileExt = PathUtil::GetExt(szFilePath);
  805.  
  806.         const bool isSKIN = stricmp(fileExt, CRY_SKIN_FILE_EXT) == 0;
  807.         if (isSKIN)
  808.         {
  809.                 CSkin* pSkin = CheckIfModelSKINLoaded(szFilePath, 0);
  810.                 if (pSkin != NULL)
  811.                 {
  812.                         if (!pSkin->m_arrModelMeshes.empty())
  813.                         {
  814.                                 int nSkinLod = clamp_tpl(nLod, 0, pSkin->m_arrModelMeshes.size() - 1);
  815.                                 return pSkin->m_arrModelMeshes[nSkinLod].m_pIRenderMesh != NULL;
  816.                         }
  817.                 }
  818.  
  819.                 return false;
  820.         }
  821.  
  822.         const bool isSKEL = stricmp(fileExt, CRY_SKEL_FILE_EXT) == 0;
  823.         const bool isCGA = stricmp(fileExt, CRY_ANIM_GEOMETRY_FILE_EXT) == 0;
  824.         if (isSKEL || isCGA)
  825.         {
  826.                 if (CDefaultSkeleton* pSkeleton = CheckIfModelSKELLoaded(szFilePath, 0))
  827.                 {
  828.                         if (CModelMesh* pModelMesh = pSkeleton->GetModelMesh())
  829.                         {
  830.                                 return (pModelMesh->m_pIRenderMesh != nullptr);
  831.                         }
  832.                 }
  833.  
  834.                 return false;
  835.         }
  836.  
  837.         const bool isCDF = stricmp(fileExt, CRY_CHARACTER_DEFINITION_FILE_EXT) == 0;
  838.         if (isCDF)
  839.         {
  840.                 return StreamKeepCDFResident(szFilePath, nLod, 0, false);
  841.         }
  842.  
  843.         return false;
  844. }
  845.  
  846. //////////////////////////////////////////////////////////////////////////
  847. ICharacterInstance* CharacterManager::CreateCGAInstance(const char* strPath, uint32 nLoadingFlags)
  848. {
  849.         LOADING_TIME_PROFILE_SECTION(g_pISystem);
  850.  
  851.         uint64 membegin = 0;
  852.         if (Console::GetInst().ca_MemoryUsageLog)
  853.         {
  854.                 //char tmp[4096];
  855.                 CryModuleMemoryInfo info;
  856.                 CryGetMemoryInfoForModule(&info);
  857.                 membegin = info.allocated - info.freed;
  858.         }
  859.  
  860.         CDefaultSkeleton* pDefaultSkeleton = (CDefaultSkeleton*)CheckIfModelSKELLoaded(strPath, nLoadingFlags);
  861.         if (pDefaultSkeleton == 0)
  862.         {
  863.                 g_pILog->UpdateLoadingScreen("Loading CGA %s", strPath);
  864.                 INDENT_LOG_DURING_SCOPE();
  865.                 pDefaultSkeleton = FetchModelSKELForGCA(strPath, nLoadingFlags);
  866.         }
  867.  
  868.         if (pDefaultSkeleton == 0)
  869.                 return NULL; // the model has not been loaded
  870.  
  871.         CCharInstance* pCryCharInstance = new CCharInstance(strPath, pDefaultSkeleton);
  872.         pCryCharInstance->m_SkeletonPose.InitCGASkeleton();
  873.  
  874.         pCryCharInstance->m_SkeletonPose.UpdateBBox(1);
  875.  
  876.         if (Console::GetInst().ca_MemoryUsageLog)
  877.         {
  878.                 CryModuleMemoryInfo info;
  879.                 CryGetMemoryInfoForModule(&info);
  880.                 g_pILog->UpdateLoadingScreen("InitCGAInstance %s. Memstat %i", strPath, (int)(info.allocated - info.freed));
  881.                 g_AnimStatisticsInfo.m_iInstancesSizes += info.allocated - info.freed - membegin;
  882.                 g_pILog->UpdateLoadingScreen("Instances Memstat %i", g_AnimStatisticsInfo.GetInstancesSize());
  883.         }
  884.  
  885.         return pCryCharInstance;
  886. }
  887.  
  888. void CharacterManager::RegisterModelSKEL(CDefaultSkeleton* pDefaultSkeleton, uint32 nLoadingFlags)
  889. {
  890.         LOADING_TIME_PROFILE_SECTION(g_pISystem);
  891.         CDefaultSkeletonReferences dsr;
  892.         dsr.m_pDefaultSkeleton = pDefaultSkeleton;
  893.         uint32 size = m_arrModelCacheSKEL.size();
  894.         if ((nLoadingFlags & CA_CharEditModel) == 0)
  895.                 m_arrModelCacheSKEL.push_back(dsr);
  896. #ifdef EDITOR_PCDEBUGCODE
  897.         else
  898.                 m_arrModelCacheSKEL_CharEdit.push_back(dsr);
  899. #endif
  900. }
  901.  
  902. // Deletes the given body from the model cache. This is done when there are no instances using this body info.
  903. void CharacterManager::UnregisterModelSKEL(CDefaultSkeleton* pDefaultSkeleton)
  904. {
  905.         uint32 numModels1 = m_arrModelCacheSKEL.size();
  906.         for (uint32 m = 0; m < numModels1; m++)
  907.         {
  908.                 if (m_arrModelCacheSKEL[m].m_pDefaultSkeleton == pDefaultSkeleton)
  909.                 {
  910.                         for (uint32 e = m; e < (numModels1 - 1); e++)
  911.                                 m_arrModelCacheSKEL[e] = m_arrModelCacheSKEL[e + 1];
  912.                         m_arrModelCacheSKEL.pop_back();
  913.                         break;
  914.                 }
  915.         }
  916.  
  917. #ifdef EDITOR_PCDEBUGCODE
  918.         uint32 numModels2 = m_arrModelCacheSKEL_CharEdit.size();
  919.         for (uint32 m = 0; m < numModels2; m++)
  920.         {
  921.                 if (m_arrModelCacheSKEL_CharEdit[m].m_pDefaultSkeleton == pDefaultSkeleton)
  922.                 {
  923.                         for (uint32 e = m; e < (numModels2 - 1); e++)
  924.                                 m_arrModelCacheSKEL_CharEdit[e] = m_arrModelCacheSKEL_CharEdit[e + 1];
  925.                         m_arrModelCacheSKEL_CharEdit.pop_back();
  926.                         break;
  927.                 }
  928.         }
  929. #endif
  930. }
  931.  
  932. void CharacterManager::RegisterInstanceSkel(CDefaultSkeleton* pDefaultSkeleton, CCharInstance* pInstance)
  933. {
  934.         uint32 numModelCacheSKEL = m_arrModelCacheSKEL.size();
  935.         for (uint32 i = 0; i < numModelCacheSKEL; i++)
  936.         {
  937.                 if (m_arrModelCacheSKEL[i].m_pDefaultSkeleton == pDefaultSkeleton)
  938.                         stl::push_back_unique(m_arrModelCacheSKEL[i].m_RefByInstances, pInstance), pDefaultSkeleton->SetInstanceCounter(m_arrModelCacheSKEL[i].m_RefByInstances.size());
  939.         }
  940. #ifdef EDITOR_PCDEBUGCODE
  941.         uint32 numModelCacheSKEL_CharEdit = m_arrModelCacheSKEL_CharEdit.size();
  942.         for (uint32 i = 0; i < numModelCacheSKEL_CharEdit; i++)
  943.         {
  944.                 if (m_arrModelCacheSKEL_CharEdit[i].m_pDefaultSkeleton == pDefaultSkeleton)
  945.                         stl::push_back_unique(m_arrModelCacheSKEL_CharEdit[i].m_RefByInstances, pInstance), pDefaultSkeleton->SetInstanceCounter(m_arrModelCacheSKEL_CharEdit[i].m_RefByInstances.size());
  946.         }
  947. #endif
  948. }
  949.  
  950. void CharacterManager::UnregisterInstanceSkel(CDefaultSkeleton* pDefaultSkeleton, CCharInstance* pInstance)
  951. {
  952.         uint32 numModelCacheSKEL = m_arrModelCacheSKEL.size();
  953.         for (uint32 i = 0; i < numModelCacheSKEL; i++)
  954.         {
  955.                 if (m_arrModelCacheSKEL[i].m_pDefaultSkeleton == pDefaultSkeleton)
  956.                         stl::find_and_erase(m_arrModelCacheSKEL[i].m_RefByInstances, pInstance), pDefaultSkeleton->SetInstanceCounter(m_arrModelCacheSKEL[i].m_RefByInstances.size());
  957.         }
  958. #ifdef EDITOR_PCDEBUGCODE
  959.         uint32 numModelCacheSKEL_CharEdit = m_arrModelCacheSKEL_CharEdit.size();
  960.         for (uint32 i = 0; i < numModelCacheSKEL_CharEdit; i++)
  961.         {
  962.                 if (m_arrModelCacheSKEL_CharEdit[i].m_pDefaultSkeleton == pDefaultSkeleton)
  963.                         stl::find_and_erase(m_arrModelCacheSKEL_CharEdit[i].m_RefByInstances, pInstance), pDefaultSkeleton->SetInstanceCounter(m_arrModelCacheSKEL_CharEdit[i].m_RefByInstances.size());
  964.         }
  965. #endif
  966. }
  967.  
  968. uint32 CharacterManager::GetNumInstancesPerModel(const IDefaultSkeleton& rIDefaultSkeleton) const
  969. {
  970.         uint32 numDefaultSkeletons = m_arrModelCacheSKEL.size();
  971.         for (uint32 m = 0; m < numDefaultSkeletons; m++)
  972.         {
  973.                 if (m_arrModelCacheSKEL[m].m_pDefaultSkeleton == &rIDefaultSkeleton)
  974.                         return m_arrModelCacheSKEL[m].m_RefByInstances.size();
  975.         }
  976.         return 0;
  977. }
  978. ICharacterInstance* CharacterManager::GetICharInstanceFromModel(const IDefaultSkeleton& rIDefaultSkeleton, uint32 num) const
  979. {
  980.         uint32 numDefaultSkeletons = m_arrModelCacheSKEL.size();
  981.         for (uint32 m = 0; m < numDefaultSkeletons; m++)
  982.         {
  983.                 if (m_arrModelCacheSKEL[m].m_pDefaultSkeleton == &rIDefaultSkeleton)
  984.                 {
  985.                         uint32 numInstance = m_arrModelCacheSKEL[m].m_RefByInstances.size();
  986.                         return (num >= numInstance) ? 0 : m_arrModelCacheSKEL[m].m_RefByInstances[num];
  987.                 }
  988.         }
  989.         return 0;
  990. }
  991.  
  992. //---------------------------------------------------------------------------------------------------
  993. /////////////////////////////////////////////////////////////////////////////////////////////////////
  994. //---------------------------------------------------------------------------------------------------
  995. void CharacterManager::RegisterModelSKIN(CSkin* pDefaultSkinning, uint32 nLoadingFlags)
  996. {
  997.         LOADING_TIME_PROFILE_SECTION(g_pISystem);
  998.         CDefaultSkinningReferences dsr;
  999.         dsr.m_pDefaultSkinning = pDefaultSkinning;
  1000.         uint32 size = m_arrModelCacheSKIN.size();
  1001.         if ((nLoadingFlags & CA_CharEditModel) == 0)
  1002.                 m_arrModelCacheSKIN.push_back(dsr);
  1003. #ifdef EDITOR_PCDEBUGCODE
  1004.         else
  1005.                 m_arrModelCacheSKIN_CharEdit.push_back(dsr);
  1006. #endif
  1007. }
  1008. // Deletes the given body from the model cache. This is done when there are no instances using this body info.
  1009. void CharacterManager::UnregisterModelSKIN(CSkin* pDefaultSkeleton)
  1010. {
  1011.         uint32 numModels1 = m_arrModelCacheSKIN.size();
  1012.         for (uint32 m = 0; m < numModels1; m++)
  1013.         {
  1014.                 if (m_arrModelCacheSKIN[m].m_pDefaultSkinning == pDefaultSkeleton)
  1015.                 {
  1016.                         for (uint32 e = m; e < (numModels1 - 1); e++)
  1017.                                 m_arrModelCacheSKIN[e] = m_arrModelCacheSKIN[e + 1];
  1018.                         m_arrModelCacheSKIN.pop_back();
  1019.                         break;
  1020.                 }
  1021.         }
  1022.  
  1023. #ifdef EDITOR_PCDEBUGCODE
  1024.         uint32 numModels2 = m_arrModelCacheSKIN_CharEdit.size();
  1025.         for (uint32 m = 0; m < numModels2; m++)
  1026.         {
  1027.                 if (m_arrModelCacheSKIN_CharEdit[m].m_pDefaultSkinning == pDefaultSkeleton)
  1028.                 {
  1029.                         for (uint32 e = m; e < (numModels2 - 1); e++)
  1030.                                 m_arrModelCacheSKIN_CharEdit[e] = m_arrModelCacheSKIN_CharEdit[e + 1];
  1031.                         m_arrModelCacheSKIN_CharEdit.pop_back();
  1032.                         break;
  1033.                 }
  1034.         }
  1035. #endif
  1036. }
  1037.  
  1038. void CharacterManager::RegisterInstanceSkin(CSkin* pDefaultSkinning, CAttachmentSKIN* pInstance)
  1039. {
  1040.         uint32 numModelCacheSKIN = m_arrModelCacheSKIN.size();
  1041.         for (uint32 i = 0; i < numModelCacheSKIN; i++)
  1042.         {
  1043.                 if (m_arrModelCacheSKIN[i].m_pDefaultSkinning == pDefaultSkinning)
  1044.                         stl::push_back_unique(m_arrModelCacheSKIN[i].m_RefByInstances, pInstance);
  1045.         }
  1046. #ifdef EDITOR_PCDEBUGCODE
  1047.         uint32 numModelCacheSKIN_CharEdit = m_arrModelCacheSKIN_CharEdit.size();
  1048.         for (uint32 i = 0; i < numModelCacheSKIN_CharEdit; i++)
  1049.         {
  1050.                 if (m_arrModelCacheSKIN_CharEdit[i].m_pDefaultSkinning == pDefaultSkinning)
  1051.                         stl::push_back_unique(m_arrModelCacheSKIN_CharEdit[i].m_RefByInstances, pInstance);
  1052.         }
  1053. #endif
  1054. }
  1055.  
  1056. void CharacterManager::UnregisterInstanceSkin(CSkin* pDefaultSkinning, CAttachmentSKIN* pInstance)
  1057. {
  1058.         uint32 numModelCacheSKIN = m_arrModelCacheSKIN.size();
  1059.         for (uint32 i = 0; i < numModelCacheSKIN; i++)
  1060.         {
  1061.                 if (m_arrModelCacheSKIN[i].m_pDefaultSkinning == pDefaultSkinning)
  1062.                         stl::find_and_erase(m_arrModelCacheSKIN[i].m_RefByInstances, pInstance);
  1063.         }
  1064. #ifdef EDITOR_PCDEBUGCODE
  1065.         uint32 numModelCacheSKIN_CharEdit = m_arrModelCacheSKIN_CharEdit.size();
  1066.         for (uint32 i = 0; i < numModelCacheSKIN_CharEdit; i++)
  1067.         {
  1068.                 if (m_arrModelCacheSKIN_CharEdit[i].m_pDefaultSkinning == pDefaultSkinning)
  1069.                         stl::find_and_erase(m_arrModelCacheSKIN_CharEdit[i].m_RefByInstances, pInstance);
  1070.         }
  1071. #endif
  1072. }
  1073.  
  1074. void CharacterManager::RegisterInstanceVCloth(CSkin* pDefaultSkinning, CAttachmentVCLOTH* pInstance)
  1075. {
  1076.         uint32 numModelCacheSKIN = m_arrModelCacheSKIN.size();
  1077.         for (uint32 i = 0; i < numModelCacheSKIN; i++)
  1078.         {
  1079.                 if (m_arrModelCacheSKIN[i].m_pDefaultSkinning == pDefaultSkinning)
  1080.                         stl::push_back_unique(m_arrModelCacheSKIN[i].m_RefByInstancesVCloth, pInstance);
  1081.         }
  1082. #ifdef EDITOR_PCDEBUGCODE
  1083.         uint32 numModelCacheSKIN_CharEdit = m_arrModelCacheSKIN_CharEdit.size();
  1084.         for (uint32 i = 0; i < numModelCacheSKIN_CharEdit; i++)
  1085.         {
  1086.                 if (m_arrModelCacheSKIN_CharEdit[i].m_pDefaultSkinning == pDefaultSkinning)
  1087.                         stl::push_back_unique(m_arrModelCacheSKIN_CharEdit[i].m_RefByInstancesVCloth, pInstance);
  1088.         }
  1089. #endif
  1090. }
  1091.  
  1092. void CharacterManager::UnregisterInstanceVCloth(CSkin* pDefaultSkinning, CAttachmentVCLOTH* pInstance)
  1093. {
  1094.         uint32 numModelCacheSKIN = m_arrModelCacheSKIN.size();
  1095.         for (uint32 i = 0; i < numModelCacheSKIN; i++)
  1096.         {
  1097.                 if (m_arrModelCacheSKIN[i].m_pDefaultSkinning == pDefaultSkinning)
  1098.                         stl::find_and_erase(m_arrModelCacheSKIN[i].m_RefByInstancesVCloth, pInstance);
  1099.         }
  1100. #ifdef EDITOR_PCDEBUGCODE
  1101.         uint32 numModelCacheSKIN_CharEdit = m_arrModelCacheSKIN_CharEdit.size();
  1102.         for (uint32 i = 0; i < numModelCacheSKIN_CharEdit; i++)
  1103.         {
  1104.                 if (m_arrModelCacheSKIN_CharEdit[i].m_pDefaultSkinning == pDefaultSkinning)
  1105.                         stl::find_and_erase(m_arrModelCacheSKIN_CharEdit[i].m_RefByInstancesVCloth, pInstance);
  1106.         }
  1107. #endif
  1108. }
  1109.  
  1110. // find wrapping projection for render mesh to simulationmesh
  1111. static inline void WrapRenderVertexToSimMesh(
  1112.   mesh_data const& simMesh,
  1113.   std::vector<std::vector<int>> const& simAdjTris,
  1114.   Vec3 const& renderVtxPos,
  1115.   SSkinMapEntry& renderVtxMapOut)
  1116. {
  1117.         // search closest particle in simMesh
  1118.         int closestIdx = -1;
  1119.         float closestDistance2 = FLT_MAX;
  1120.         for (int i = 0; i < simMesh.nVertices; i++)
  1121.         {
  1122.                 Vec3 delta = renderVtxPos - simMesh.pVertices[i];
  1123.                 float len2 = delta.len2();
  1124.                 if (len2 < closestDistance2) { closestIdx = i; closestDistance2 = len2; }
  1125.         }
  1126.  
  1127.         // if render particle is very close to sim particle, then use direct mapping to that position
  1128.         const float threshold2 = 0.001f * 0.001f;
  1129.         if (closestDistance2 < threshold2)
  1130.         {
  1131.                 renderVtxMapOut.iMap = closestIdx;
  1132.                 renderVtxMapOut.s = 0.f;
  1133.                 renderVtxMapOut.t = 0.f;
  1134.                 renderVtxMapOut.h = 0.f;
  1135.                 return;
  1136.         }
  1137.  
  1138.         // search triangle with positive uv - this is the ideal case
  1139.         // go through all the adjacent triangles and find the best fit
  1140.         for (size_t j = 0; j < simAdjTris[closestIdx].size(); j++)
  1141.         {
  1142.                 const int tri = simAdjTris[closestIdx][j];
  1143.  
  1144.                 // get triangles side/neighbor vertices to closest point
  1145.                 int i2 = 0;
  1146.                 for (int k = 0; k < 3; k++)
  1147.                 {
  1148.                         int idx = simMesh.pIndices[tri * 3 + k];
  1149.                         if (idx == closestIdx)
  1150.                                 i2 = k;
  1151.                 }
  1152.                 const int idx0 = simMesh.pIndices[tri * 3 + inc_mod3[i2]];
  1153.                 const int idx1 = simMesh.pIndices[tri * 3 + dec_mod3[i2]];
  1154.  
  1155.                 // barycentric and distance to render mesh
  1156.                 float s, t, h;
  1157.                 const Vec3 u = simMesh.pVertices[idx0] - simMesh.pVertices[closestIdx];
  1158.                 const Vec3 v = simMesh.pVertices[idx1] - simMesh.pVertices[closestIdx];
  1159.                 Vec3 w = renderVtxPos - simMesh.pVertices[closestIdx];
  1160.                 Vec3 n = (u ^ v).normalized();
  1161.                 h = w * n;
  1162.                 w -= h * n;
  1163.                 const float d00 = u * u;
  1164.                 const float d01 = u * v;
  1165.                 const float d11 = v * v;
  1166.                 const float d20 = w * u;
  1167.                 const float d21 = w * v;
  1168.                 const float denom = d00 * d11 - d01 * d01;
  1169.                 s = (d11 * d20 - d01 * d21) / denom;
  1170.                 t = (d00 * d21 - d01 * d20) / denom;
  1171.  
  1172.                 // if s,t are positive, keep this value, as it is a good mapping
  1173.                 // if either s or t is < 0 - set this only, if no other tri (e.g., with positive uv) has been found, not ideal but in worst case better than nothing...
  1174.                 if ((s >= 0 && t >= 0) || (renderVtxMapOut.iTri < 0))
  1175.                 {
  1176.                         renderVtxMapOut.iMap = i2;
  1177.                         renderVtxMapOut.iTri = tri;
  1178.                         renderVtxMapOut.s = s;
  1179.                         renderVtxMapOut.t = t;
  1180.                         renderVtxMapOut.h = h;
  1181.                 }
  1182.         }
  1183. }
  1184.  
  1185. SClothGeometry* CharacterManager::LoadVClothGeometry(const CAttachmentVCLOTH& pAttachementVCloth, _smart_ptr<IRenderMesh> pRenderMeshes[])
  1186. {
  1187.         assert(pAttachementVCloth.GetClothCacheKey() > 0);
  1188.         SClothGeometry& ret = m_clothGeometries[pAttachementVCloth.GetClothCacheKey()];
  1189.         if (ret.weldMap != NULL)
  1190.         {
  1191.                 ret.AllocateBuffer();
  1192.                 return &ret;
  1193.         }
  1194.  
  1195.         IRenderMesh* pSimRenderMesh = pAttachementVCloth.m_pSimSkin->GetIRenderMesh(0);
  1196.         ret.nVtx = pSimRenderMesh->GetVerticesCount();
  1197.         int nSimIndices = pSimRenderMesh->GetIndicesCount();
  1198.  
  1199.         pSimRenderMesh->LockForThreadAccess();
  1200.         strided_pointer<Vec3> pVertices;
  1201.         pVertices.data = (Vec3*)pSimRenderMesh->GetPosPtr(pVertices.iStride, FSL_READ);
  1202.         vtx_idx* pSimIndices = pSimRenderMesh->GetIndexPtr(FSL_READ);
  1203.         strided_pointer<ColorB> pColors(0);
  1204.         pColors.data = (ColorB*)pSimRenderMesh->GetColorPtr(pColors.iStride, FSL_READ);
  1205.  
  1206.         // look for welded vertices and prune them
  1207.         int nWelded = 0;
  1208.         std::vector<Vec3> unweldedVerts;
  1209.         unweldedVerts.reserve(ret.nVtx);
  1210.         if (!ret.weldMap)
  1211.                 ret.weldMap = new vtx_idx[ret.nVtx];
  1212.         // TODO: faster welded vertices detector - this is O(n^2)
  1213.         for (int i = 0; i < ret.nVtx; i++)
  1214.         {
  1215.                 int iMap = -1;
  1216.                 for (int j = i - 1; j >= 0; j--)
  1217.                 {
  1218.                         Vec3 delta = pVertices[i] - pVertices[j];
  1219.                         if (delta.len() < 0.001f)
  1220.                         {
  1221.                                 iMap = ret.weldMap[j];
  1222.                                 nWelded++;
  1223.                                 break;
  1224.                         }
  1225.                 }
  1226.                 if (iMap >= 0)
  1227.                         ret.weldMap[i] = iMap;
  1228.                 else
  1229.                 {
  1230.                         ret.weldMap[i] = unweldedVerts.size();
  1231.                         unweldedVerts.push_back(pVertices[i]);
  1232.                 }
  1233.         }
  1234.         if (nWelded)
  1235.                 CryLog("[Character Cloth] Found %d welded vertices out of %d in attachment %s", nWelded, ret.nVtx, pAttachementVCloth.GetName());
  1236.         // reconstruct indices
  1237.         vtx_idx* unweldedIndices = new vtx_idx[nSimIndices];
  1238.         ret.nUniqueVtx = unweldedVerts.size();
  1239.         for (int i = 0; i < nSimIndices; i++)
  1240.                 unweldedIndices[i] = ret.weldMap[pSimIndices[i]];
  1241.  
  1242.         // create the physics geometry (CTriMesh)
  1243.         IGeometry* pSimPhysMesh = g_pIPhysicalWorld->GetGeomManager()->CreateMesh(&unweldedVerts[0], unweldedIndices, 0, 0, nSimIndices / 3, 0);
  1244.  
  1245.         delete[] unweldedIndices;
  1246.  
  1247.         // register phys geometry
  1248.         ret.pPhysGeom = g_pIPhysicalWorld->GetGeomManager()->RegisterGeometry(pSimPhysMesh);
  1249.         pSimPhysMesh->Release();
  1250.  
  1251.         // compute blending weights from vertex colors
  1252.         ret.weights = new float[ret.nUniqueVtx];
  1253.         for (int i = 0; i < ret.nVtx; i++)
  1254.         {
  1255.                 float alpha = 1.f - (float)pColors[i].r / 255.f;
  1256.                 ret.weights[ret.weldMap[i]] = alpha;
  1257.         }
  1258.  
  1259.         pSimRenderMesh->UnlockStream(VSF_TANGENTS);
  1260.         pSimRenderMesh->UnlockStream(VSF_HWSKIN_INFO);
  1261.         pSimRenderMesh->UnlockStream(VSF_GENERAL);
  1262.         pSimRenderMesh->UnLockForThreadAccess();
  1263.  
  1264.         // build adjacent triangles list
  1265.         mesh_data* md = (mesh_data*)pSimPhysMesh->GetData();
  1266.         std::vector<std::vector<int>> adjTris(md->nVertices);
  1267.         for (int i = 0; i < md->nTris; i++)
  1268.         {
  1269.                 for (int j = 0; j < 3; j++)
  1270.                 {
  1271.                         int idx = md->pIndices[i * 3 + j];
  1272.                         adjTris[idx].push_back(i);
  1273.                 }
  1274.         }
  1275.  
  1276.         ret.maxVertices = 0;
  1277.         for (int lod = 0; lod < SClothGeometry::MAX_LODS; lod++)
  1278.         {
  1279.                 IRenderMesh* pRenderMesh = pRenderMeshes[lod];
  1280.                 if (!pRenderMesh)
  1281.                         continue;
  1282.  
  1283.                 int nVtx = pRenderMesh->GetVerticesCount();
  1284.                 ret.maxVertices = max(ret.maxVertices, nVtx);
  1285.                 int nIndices = pRenderMesh->GetIndicesCount();
  1286.                 ret.numIndices[lod] = nIndices;
  1287.                 int nTris = nIndices / 3;
  1288.  
  1289.                 pRenderMesh->LockForThreadAccess();
  1290.                 vtx_idx* pIndices = pRenderMesh->GetIndexPtr(FSL_READ);
  1291.                 ret.pIndices[lod] = new vtx_idx[nIndices];
  1292.                 memcpy(ret.pIndices[lod], pIndices, nIndices * sizeof(vtx_idx));
  1293.  
  1294.                 strided_pointer<Vec3> pVtx;
  1295.                 pVtx.data = (Vec3*)pRenderMesh->GetPosPtr(pVtx.iStride, FSL_READ);
  1296.                 strided_pointer<Vec2> pUVs;
  1297.                 pUVs.data = (Vec2*)pRenderMesh->GetUVPtr(pUVs.iStride, FSL_READ);
  1298.  
  1299.                 SSkinMapEntry* skinMap = new SSkinMapEntry[nVtx];
  1300.                 ret.skinMap[lod] = skinMap;
  1301.                 int numUnmapped = 0;
  1302.                 for (int i = 0; i < nVtx; i++)
  1303.                 {
  1304.                         // init as 'no skinning/triangle-mapping found', this is used below to detect the number of unmapped vertices
  1305.                         skinMap[i].iTri = -1;
  1306.  
  1307.                         // wrap render mesh to sim mesh
  1308.                         mesh_data const& simMesh = *md;
  1309.                         std::vector<std::vector<int>> const& simAdjTris = adjTris;
  1310.                         Vec3 const& renderVtx = pVtx[i];
  1311.                         SSkinMapEntry& renderVtxMap = skinMap[i];
  1312.                         WrapRenderVertexToSimMesh(simMesh, simAdjTris, renderVtx, renderVtxMap); // determine best wrapping in 'renderVtxMap', i.e. skinMap[i]
  1313.  
  1314.                         if (skinMap[i].iTri < 0)
  1315.                         {
  1316.                                 numUnmapped++;
  1317.                         }
  1318.                 }
  1319.                 if (numUnmapped)
  1320.                         CryLog("[Character cloth] Unmapped vertices: %d", numUnmapped);
  1321.  
  1322.                 // prepare tangent data
  1323.                 ret.tangentData[lod] = new STangentData[nTris];
  1324.                 for (int i = 0; i < nTris; i++)
  1325.                 {
  1326.                         int base = i * 3;
  1327.                         int i1 = pIndices[base++];
  1328.                         int i2 = pIndices[base++];
  1329.                         int i3 = pIndices[base];
  1330.  
  1331.                         const Vec3& v1 = pVtx[i1];
  1332.                         const Vec3& v2 = pVtx[i2];
  1333.                         const Vec3& v3 = pVtx[i3];
  1334.  
  1335.                         Vec3 u = v2 - v1;
  1336.                         Vec3 v = v3 - v1;
  1337.  
  1338.                         float w1x = pUVs[i1].x;
  1339.                         float w1y = pUVs[i1].y;
  1340.                         float w2x = pUVs[i2].x;
  1341.                         float w2y = pUVs[i2].y;
  1342.                         float w3x = pUVs[i3].x;
  1343.                         float w3y = pUVs[i3].y;
  1344.  
  1345.                         float s1 = w2x - w1x;
  1346.                         float s2 = w3x - w1x;
  1347.                         float t1 = w2y - w1y;
  1348.                         float t2 = w3y - w1y;
  1349.  
  1350.                         const float denom = s1 * t2 - s2 * t1;
  1351.                         float r = fabsf(denom) > FLT_EPSILON ? 1.0f / denom : 1.0f;
  1352.  
  1353.                         ret.tangentData[lod][i].t1 = t1;
  1354.                         ret.tangentData[lod][i].t2 = t2;
  1355.                         ret.tangentData[lod][i].r = r;
  1356.                 }
  1357.  
  1358.                 pRenderMesh->UnlockStream(VSF_GENERAL);
  1359.                 pRenderMesh->UnLockForThreadAccess();
  1360.         }
  1361.  
  1362.         // allocate working buffers
  1363.         ret.AllocateBuffer();
  1364.  
  1365.         return &ret;
  1366. }
  1367.  
  1368. #ifdef EDITOR_PCDEBUGCODE
  1369. void CharacterManager::ClearAllKeepInMemFlags()
  1370. {
  1371.         uint32 numModelCacheSKEL_CharEdit = m_arrModelCacheSKEL_CharEdit.size();
  1372.         for (uint32 i = 0; i < numModelCacheSKEL_CharEdit; i++)
  1373.                 m_arrModelCacheSKEL_CharEdit[i].m_pDefaultSkeleton->SetKeepInMemory(false);
  1374.  
  1375.         uint32 numModelCacheSKIN_CharEdit = m_arrModelCacheSKIN_CharEdit.size();
  1376.         for (uint32 i = 0; i < numModelCacheSKIN_CharEdit; i++)
  1377.                 m_arrModelCacheSKIN_CharEdit[i].m_pDefaultSkinning->SetKeepInMemory(false);
  1378.  
  1379.         for (int32 i = (numModelCacheSKEL_CharEdit - 1); i > -1; i--)
  1380.                 m_arrModelCacheSKEL_CharEdit[i].m_pDefaultSkeleton->DeleteIfNotReferenced();
  1381.         for (int32 i = (numModelCacheSKIN_CharEdit - 1); i > -1; i--)
  1382.                 m_arrModelCacheSKIN_CharEdit[i].m_pDefaultSkinning->DeleteIfNotReferenced();
  1383. }
  1384. #endif
  1385.  
  1386. //////////////////////////////////////////////////////////////////////////
  1387.  
  1388. // Deletes itself
  1389. void CharacterManager::Release()
  1390. {
  1391.         delete this;
  1392. }
  1393.  
  1394. //////////////////////////////////////////////////////////////////////////
  1395. IFacialAnimation* CharacterManager::GetIFacialAnimation()
  1396. {
  1397.         return m_pFacialAnimation;
  1398. }
  1399.  
  1400. //////////////////////////////////////////////////////////////////////////
  1401. const IFacialAnimation* CharacterManager::GetIFacialAnimation() const
  1402. {
  1403.         return m_pFacialAnimation;
  1404. }
  1405.  
  1406. const IAttachmentMerger& CharacterManager::GetIAttachmentMerger() const
  1407. {
  1408.         return CAttachmentMerger::Instance();
  1409. }
  1410.  
  1411. // returns statistics about this instance of character animation manager
  1412. // don't call this too frequently
  1413. void CharacterManager::GetStatistics(Statistics& rStats) const
  1414. {
  1415.         memset(&rStats, 0, sizeof(rStats));
  1416.         rStats.numCharModels = m_arrModelCacheSKEL.size();
  1417.         for (uint32 m = 0; m < rStats.numCharModels; m++)
  1418.                 rStats.numCharacters += m_arrModelCacheSKEL[m].m_RefByInstances.size();
  1419. }
  1420.  
  1421. // puts the size of the whole subsystem into this sizer object, classified,
  1422. // according to the flags set in the sizer
  1423. void CharacterManager::GetMemoryUsage(class ICrySizer* pSizer) const
  1424. {
  1425.         pSizer->AddObject(this, sizeof(*this));
  1426.         pSizer->AddObject(m_AnimationManager);
  1427.         pSizer->AddObject(m_arrCacheForCDF);
  1428.         pSizer->AddObject(g_AnimationManager);
  1429.         {
  1430.                 SIZER_SUBCOMPONENT_NAME(pSizer, "Facial Animation");
  1431.                 pSizer->AddObject(m_pFacialAnimation);
  1432.         }
  1433.         {
  1434.                 SIZER_SUBCOMPONENT_NAME(pSizer, "Model Data");
  1435.                 pSizer->AddObject(m_arrModelCacheSKEL);
  1436.         }
  1437.  
  1438.         GetCharacterInstancesSize(pSizer);
  1439.  
  1440. #ifndef _LIB // Only when compiling as dynamic library
  1441.         {
  1442.                 //SIZER_COMPONENT_NAME(pSizer,"Strings");
  1443.                 //pSizer->AddObject( (this+1),string::_usedMemory(0) );
  1444.         }
  1445.         {
  1446.                 SIZER_COMPONENT_NAME(pSizer, "STL Allocator Waste");
  1447.                 CryModuleMemoryInfo meminfo;
  1448.                 ZeroStruct(meminfo);
  1449.                 CryGetMemoryInfoForModule(&meminfo);
  1450.                 pSizer->AddObject((this + 2), (uint32)meminfo.STL_wasted);
  1451.         }
  1452. #endif
  1453.  
  1454.         {
  1455.                 SIZER_SUBCOMPONENT_NAME(pSizer, "Animation Context");
  1456.                 pSizer->AddObject(CAnimationContext::Instance());
  1457.         }
  1458. }
  1459.  
  1460. void CharacterManager::GetModelCacheSize() const
  1461. {
  1462.         uint32 numModels = m_arrModelCacheSKEL.size();
  1463.         for (uint32 i = 0; i < numModels; i++)
  1464.                 m_arrModelCacheSKEL[i].m_pDefaultSkeleton->SizeOfDefaultSkeleton();
  1465. }
  1466.  
  1467. void CharacterManager::GetCharacterInstancesSize(class ICrySizer* pSizer) const
  1468. {
  1469.         SIZER_SUBCOMPONENT_NAME(pSizer, "Character instances");
  1470.  
  1471.         uint32 nSize = 0;
  1472.         uint32 numModelCache = m_arrModelCacheSKEL.size();
  1473.         for (uint32 m = 0; m < numModelCache; ++m)
  1474.         {
  1475.                 uint32 numInstances = m_arrModelCacheSKEL[m].m_RefByInstances.size();
  1476.                 for (uint32 i = 0; i < numInstances; i++)
  1477.                         pSizer->AddObject(m_arrModelCacheSKEL[m].m_RefByInstances[i]);
  1478.         }
  1479.  
  1480. }
  1481.  
  1482. //! Cleans up all resources - currently deletes all bodies and characters (even if there are references on them)
  1483. void CharacterManager::ClearResources(bool bForceCleanup)
  1484. {
  1485.         ClearPoseModifiersFromSynchQueue();
  1486.         SyncAllAnimations();
  1487.         StopAnimationsOnAllInstances();
  1488.  
  1489.         // clean animations cache and statistics
  1490.         if (m_pFacialAnimation)
  1491.                 m_pFacialAnimation->ClearAllCaches();
  1492.  
  1493.         if (!gEnv->IsEditor())
  1494.                 CleanupModelCache(bForceCleanup);
  1495.         GetAnimationManager().Unload_All_Animation();
  1496. }
  1497.  
  1498. //////////////////////////////////////////////////////////////////////////
  1499. // Deletes all the cached bodies and their associated character instances
  1500. void CharacterManager::CleanupModelCache(bool bForceCleanup)
  1501. {
  1502.  
  1503. #if PLACEHOLDER_CHARACTER_DEBUG_ENABLE
  1504.         CryLogAlways("CharacterManager:CleanModelCache - Placeholder objects '%d'", CPlaceholderCharacter::GetAllocatedObjects());
  1505. #endif
  1506.  
  1507.         uint32 numSKEL1 = m_arrModelCacheSKEL.size();
  1508.         for (uint32 i = 0; i < numSKEL1; i++)
  1509.                 m_arrModelCacheSKEL[i].m_pDefaultSkeleton->SetKeepInMemory(true);   // Make sure nothing gets deleted.
  1510.  
  1511.         int32 numSKEL2 = m_arrModelCacheSKEL.size();                            // Clean all instances.
  1512.         for (int32 s = (numSKEL2 - 1); s > -1; s--)
  1513.         {
  1514.                 int numInstances = m_arrModelCacheSKEL[s].m_RefByInstances.size();
  1515.                 if (numInstances)
  1516.                         g_pISystem->Warning(VALIDATOR_MODULE_ANIMATION, VALIDATOR_WARNING, 0, "CharacterManager.CleanupInstances", "Forcing deletion of %d instances for body %s. CRASH POSSIBLE because other subsystems may have stored dangling pointer(s).", m_arrModelCacheSKEL[s].m_pDefaultSkeleton->GetRefCounter(), m_arrModelCacheSKEL[s].m_pDefaultSkeleton->m_strFilePath.c_str());
  1517.                 for (int32 i = (numInstances - 1); i > -1; i--)
  1518.                         delete m_arrModelCacheSKEL[s].m_RefByInstances[i];
  1519.         }
  1520.  
  1521.         uint32 numSKEL3 = m_arrModelCacheSKEL.size();                           //count backwards, because the array is decreased after each delete.
  1522.         for (int32 i = (numSKEL3 - 1); i > -1; i--)
  1523.                 m_arrModelCacheSKEL[i].m_pDefaultSkeleton->DeleteIfNotReferenced(); //even if locked in memory
  1524.  
  1525.         uint32 numSKEL4 = m_arrModelCacheSKEL.size();                           //if we still have instances, then something went wrong
  1526.         if (numSKEL4)
  1527.         {
  1528.                 for (uint32 i = 0; i < numSKEL4; i++)
  1529.                         CryLogAlways("m_arrModelCacheSKEL[%i] = %s", i, m_arrModelCacheSKEL[i].m_pDefaultSkeleton->GetModelFilePath());
  1530.                 CryFatalError("m_arrModelCacheSKEL is supposed to be empty, but there are still %d CSkels in memory", numSKEL4);
  1531.         }
  1532.  
  1533.         //----------------------------------------------------------------------------------------------------------------------
  1534.  
  1535.         uint32 numSKIN1 = m_arrModelCacheSKIN.size();
  1536.         for (uint32 i = 0; i < numSKIN1; i++)
  1537.                 m_arrModelCacheSKIN[i].m_pDefaultSkinning->SetKeepInMemory(true);   // Make sure nothing gets deleted.
  1538.  
  1539.         int32 numSKIN2 = m_arrModelCacheSKIN.size();                            // Clean all instances.
  1540.         for (int32 s = (numSKIN2 - 1); s > -1; s--)
  1541.         {
  1542.                 int numInstances = m_arrModelCacheSKIN[s].m_RefByInstances.size();
  1543.                 if (numInstances)
  1544.                         g_pISystem->Warning(VALIDATOR_MODULE_ANIMATION, VALIDATOR_WARNING, 0, "CharacterManager.CleanupSkinInstances", "Forcing deletion of %d instances for body %s. CRASH POSSIBLE because other subsystems may have stored dangling pointer(s).", m_arrModelCacheSKIN[s].m_pDefaultSkinning->GetRefCounter(), m_arrModelCacheSKIN[s].m_pDefaultSkinning->GetModelFilePath());
  1545.                 for (int32 i = (numInstances - 1); i > -1; i--)
  1546.                         delete m_arrModelCacheSKIN[s].m_RefByInstances[i];
  1547.  
  1548.                 int numVClothInstances = m_arrModelCacheSKIN[s].m_RefByInstancesVCloth.size();
  1549.                 if (numVClothInstances)
  1550.                         g_pISystem->Warning(VALIDATOR_MODULE_ANIMATION, VALIDATOR_WARNING, 0, "CharacterManager.CleanupVClothInstances", "Forcing deletion of %d instances for body %s. CRASH POSSIBLE because other subsystems may have stored dangling pointer(s).", m_arrModelCacheSKIN[s].m_pDefaultSkinning->GetRefCounter(), m_arrModelCacheSKIN[s].m_pDefaultSkinning->GetModelFilePath());
  1551.                 for (int32 i = (numVClothInstances - 1); i > -1; i--)
  1552.                         delete m_arrModelCacheSKIN[s].m_RefByInstancesVCloth[i];
  1553.         }
  1554.  
  1555.         uint32 numSKIN3 = m_arrModelCacheSKIN.size();                           //count backwards, because the array is decreased after each delete.
  1556.         for (int32 i = (numSKIN3 - 1); i > -1; i--)
  1557.                 m_arrModelCacheSKIN[i].m_pDefaultSkinning->DeleteIfNotReferenced(); //even if locked in memory
  1558.  
  1559.         uint32 numSKIN4 = m_arrModelCacheSKIN.size();                           //if we still have instances, then something went wrong
  1560.         if (numSKIN4)
  1561.         {
  1562.                 for (uint32 i = 0; i < numSKIN4; i++)
  1563.                         CryLogAlways("m_arrModelCacheSKIN[%i] = %s", i, m_arrModelCacheSKIN[i].m_pDefaultSkinning->GetModelFilePath());
  1564.                 CryFatalError("m_arrModelCacheSKIN is supposed to be empty, but there are still %d CSkins in memory", numSKIN4);
  1565.         }
  1566.  
  1567.         CryCHRLoader::ClearCachedLodSkeletonResults();
  1568.  
  1569.         if (bForceCleanup)
  1570.         {
  1571.                 m_arrCacheForCDF.clear();
  1572.                 for (TClothGeomCache::iterator it = m_clothGeometries.begin(); it != m_clothGeometries.end(); ++it)
  1573.                 {
  1574.                         it->second.Cleanup();
  1575.                 }
  1576.         }
  1577.  
  1578.         CFacialModel::ClearResources();
  1579. }
  1580.  
  1581. //------------------------------------------------------------------------
  1582. //--  average frame-times to avoid stalls and peaks in framerate
  1583. //------------------------------------------------------------------------
  1584. f32 CharacterManager::GetAverageFrameTime(f32 sec, f32 FrameTime, f32 fTimeScale, f32 LastAverageFrameTime)
  1585. {
  1586.         uint32 numFT = m_arrFrameTimes.size();
  1587.         for (int32 i = (numFT - 2); i > -1; i--)
  1588.                 m_arrFrameTimes[i + 1] = m_arrFrameTimes[i];
  1589.  
  1590.         m_arrFrameTimes[0] = FrameTime;
  1591.  
  1592.         //get smoothed frame
  1593.         uint32 FrameAmount = 1;
  1594.         if (LastAverageFrameTime)
  1595.         {
  1596.                 FrameAmount = uint32(sec / LastAverageFrameTime * fTimeScale + 0.5f);         //average the frame-times for a certain time-period (sec)
  1597.                 if (FrameAmount > numFT)  FrameAmount = numFT;
  1598.                 if (FrameAmount < 1)  FrameAmount = 1;
  1599.         }
  1600.  
  1601.         f32 AverageFrameTime = 0;
  1602.         for (uint32 i = 0; i < FrameAmount; i++)
  1603.                 AverageFrameTime += m_arrFrameTimes[i];
  1604.         AverageFrameTime /= FrameAmount;
  1605.  
  1606.         //don't smooth if we pase the game
  1607.         if (FrameTime < 0.0001f)
  1608.                 AverageFrameTime = FrameTime;
  1609.  
  1610.         //      g_YLine+=66.0f;
  1611.         //      float fColor[4] = {1,0,1,1};
  1612.         //      g_pAuxGeom->Draw2dLabel( 1,g_YLine, 1.3f, fColor, false,"AverageFrameTime:  Frames:%d  FrameTime:%f  AverageTime:%f", FrameAmount, FrameTime, AverageFrameTime);
  1613.         //      g_YLine+=16.0f;
  1614.  
  1615.         return AverageFrameTime;
  1616. }
  1617.  
  1618. uint32 CharacterManager::GetRendererThreadId()
  1619. {
  1620.         bool bIsMultithreadedRenderer = false;
  1621.         g_pIRenderer->EF_Query(EFQ_RenderMultithreaded, bIsMultithreadedRenderer);
  1622.         if (bIsMultithreadedRenderer)
  1623.         {
  1624.                 static uint32 frameId = 0;
  1625.                 if (!s_bPaused)
  1626.                         frameId = (uint32)g_pIRenderer->GetFrameID(false);
  1627.                 return frameId;
  1628.         }
  1629.  
  1630.         return s_renderFrameIdLocal;
  1631. }
  1632.  
  1633. uint32 CharacterManager::GetRendererMainThreadId()
  1634. {
  1635.         bool bIsMultithreadedRenderer = false;
  1636.         g_pIRenderer->EF_Query(EFQ_RenderMultithreaded, bIsMultithreadedRenderer);
  1637.         if (bIsMultithreadedRenderer)
  1638.         {
  1639.                 static uint32 frameId = 0;
  1640.                 if (!s_bPaused)
  1641.                         frameId = (uint32)g_pIRenderer->GetFrameID(false);
  1642.                 return frameId;
  1643.         }
  1644.  
  1645.         return s_renderFrameIdLocal;
  1646. }
  1647.  
  1648. void CharacterManager::UpdateRendererFrame()
  1649. {
  1650.         s_renderFrameIdLocal++;
  1651. }
  1652.  
  1653. // should be called every frame
  1654. void CharacterManager::Update(bool bPaused)
  1655. {
  1656.         s_bPaused = bPaused;
  1657.         CRY_PROFILE_REGION(PROFILE_ANIMATION, "CharacterManager::Update");
  1658.         CRYPROFILE_SCOPE_PROFILE_MARKER("CharacterManager::Update");
  1659.         ANIMATION_LIGHT_PROFILER();
  1660.  
  1661.         CAnimationContext::Instance().Update();
  1662.  
  1663.         m_nUpdateCounter++;
  1664.  
  1665.         //update interfaces every frame
  1666.         g_YLine = 16.0f;
  1667.         g_pIRenderer = g_pISystem->GetIRenderer();
  1668.         g_pIPhysicalWorld = g_pISystem->GetIPhysicalWorld();
  1669.         g_pI3DEngine = g_pISystem->GetI3DEngine();
  1670.         g_bProfilerOn = g_pISystem->GetIProfileSystem()->IsProfiling();
  1671.  
  1672.         bool bIsMultithreadedRenderer = false;
  1673.         if (g_pIRenderer)
  1674.                 g_pIRenderer->EF_Query(EFQ_RenderMultithreaded, bIsMultithreadedRenderer);
  1675.  
  1676.         if (!bIsMultithreadedRenderer && !s_bPaused)
  1677.                 s_renderFrameIdLocal++;
  1678.  
  1679.         g_fCurrTime = g_pITimer->GetCurrTime();
  1680.  
  1681.         if (m_InitializedByIMG == 0)
  1682.         {
  1683.                 //This initialization must happen as early as possible. In the ideal case we should do it as soon as we initialize CryAnimation.
  1684.                 //Doing it when we fetch the CHR is to late, because it will conflict with manually loaded DBAs (MP can load DBA and lock DBAs without a CHR)
  1685.                 //LoadAnimationImageFile( "animations/animations.img","animations/DirectionalBlends.img" );
  1686.         }
  1687.  
  1688.         f32 fTimeScale = g_pITimer->GetTimeScale();
  1689.         f32 fFrameTime = g_pITimer->GetFrameTime();
  1690.         if (fFrameTime > 0.2f) fFrameTime = 0.2f;
  1691.         if (fFrameTime < 0.0f) fFrameTime = 0.0f;
  1692.         g_AverageFrameTime = GetAverageFrameTime(0.25f, fFrameTime, fTimeScale, g_AverageFrameTime);
  1693.  
  1694.         CVertexAnimation::ClearSoftwareRenderMeshes();
  1695.  
  1696.         /*
  1697.            #ifndef _RELEASE
  1698.            uint32 num=g_DataMismatch.size();
  1699.            for (uint32 i=0; i<num; i++)
  1700.            {
  1701.             float fColor[4] = {0,1,1,1};
  1702.             g_pAuxGeom->Draw2dLabel( 1,g_YLine, 1.4f, fColor, false,"FatalError: Data-Mismatch for Streaming File %s",g_DataMismatch[i].c_str() );
  1703.             g_YLine+=14.0f;
  1704.            }
  1705.            #endif
  1706.          */
  1707.  
  1708.  
  1709.         UpdateInstances(bPaused);
  1710.  
  1711.         if (Console::GetInst().ca_DebugModelCache)
  1712.         {
  1713.                 float fWhite[4] = { 1, 1, 1, 1 };
  1714. #ifdef EDITOR_PCDEBUGCODE
  1715.                 uint32 numMCSkelCE = m_arrModelCacheSKEL_CharEdit.size();
  1716.                 uint32 numMCSkinCE = m_arrModelCacheSKIN_CharEdit.size();
  1717.                 if (numMCSkelCE + numMCSkinCE)
  1718.                 {
  1719.                         g_pAuxGeom->Draw2dLabel(1, g_YLine, 2.0f, fWhite, false, "arrModelCache_CharEdit: %4d", numMCSkelCE), g_YLine += 20.0f;
  1720.                         DebugModelCache(1, m_arrModelCacheSKEL_CharEdit, m_arrModelCacheSKIN_CharEdit);
  1721.                         g_pAuxGeom->Draw2dLabel(1, g_YLine, 2.0f, fWhite, false, "-----------------------------"), g_YLine += 20.0f;
  1722.                 }
  1723. #endif
  1724.                 DebugModelCache(1, m_arrModelCacheSKEL, m_arrModelCacheSKIN);
  1725. #ifndef _RELEASE
  1726.                 Console::GetInst().ca_DebugModelCache &= 0x17;   //disable logging to console
  1727. #endif
  1728.         }
  1729.         if (Console::GetInst().ca_ReloadAllCHRPARAMS)
  1730.                 ReloadAllCHRPARAMS();
  1731.         if (Console::GetInst().ca_DebugAnimUsage)
  1732.                 GetAnimationManager().DebugAnimUsage(1);
  1733.         if (Console::GetInst().ca_UnloadAnimationDBA)
  1734.                 DatabaseUnloading();
  1735.  
  1736.         if (Console::GetInst().ca_DebugAnimMemTracking)
  1737.         {
  1738.                 //Test if memory tracking works
  1739.                 float fBlue[4] = { 0, 0, 1, 1 };
  1740.                 g_YLine += 10.0f;
  1741.                 if (g_AnimationManager.m_AnimMemoryTracker.m_nAnimsCounter)
  1742.                 {
  1743.                         uint64 average = g_AnimationManager.m_AnimMemoryTracker.m_nAnimsAdd / g_AnimationManager.m_AnimMemoryTracker.m_nAnimsCounter;
  1744.                         g_pAuxGeom->Draw2dLabel(1, g_YLine, 2.0f, fBlue, false, "nAnimsPerFrame: %4d  nAnimsMax: %4d nAnimsAvrg: %4d", g_AnimationManager.m_AnimMemoryTracker.m_nAnimsCurrent / 1024, g_AnimationManager.m_AnimMemoryTracker.m_nAnimsMax / 1024, (uint32)(average / 1024));
  1745.                         g_YLine += 16.0f;
  1746.                 }
  1747.         }
  1748.  
  1749.         if (Console::GetInst().ca_DebugAnimUpdates)
  1750.         {
  1751.                 float fColor[4] = { 0, 1, 1, 1 };
  1752.                 g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.3f, fColor, false, "AnimationUpdates: %d", g_AnimationUpdates);
  1753.                 g_YLine += 16.0f;
  1754.                 g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.3f, fColor, false, "SkeletonUpdates: %d", g_SkeletonUpdates);
  1755.                 g_YLine += 16.0f;
  1756.  
  1757.                 uint32 numFSU = m_arrSkeletonUpdates.size();
  1758.                 g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.3f, fColor, false, "Instances with 'Force Skeleton Update': %d", numFSU);
  1759.                 g_YLine += 16.0f;
  1760.                 for (uint32 i = 0; i < numFSU; i++)
  1761.                 {
  1762.                         g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.2f, fColor, false, "Anim:(%d)  Force:(%d)  Visible:(%d)  ModelPath: %s", m_arrAnimPlaying[i], m_arrForceSkeletonUpdates[i], m_arrVisible[i], m_arrSkeletonUpdates[i].c_str());
  1763.                         g_YLine += 14.0f;
  1764.                 }
  1765.         }
  1766.         g_AnimationUpdates = 0;
  1767.         g_SkeletonUpdates = 0;
  1768.  
  1769.         m_arrSkeletonUpdates.resize(0);
  1770.         m_arrAnimPlaying.resize(0);
  1771.         m_arrForceSkeletonUpdates.resize(0);
  1772.         m_arrVisible.resize(0);
  1773.  
  1774. #ifndef CONSOLE_CONST_CVAR_MODE
  1775.         if (Console::GetInst().ca_DumpUsedAnims)
  1776.         {
  1777.                 DumpAssetStatistics();
  1778.                 Console::GetInst().ca_DumpUsedAnims = 0;
  1779.         }
  1780. #endif
  1781.  
  1782. #ifndef _RELEASE
  1783.         if (Console::GetInst().ca_vaProfile != 0)
  1784.         {
  1785.                 g_vertexAnimationProfiler.DrawVertexAnimationStats(Console::GetInst().ca_vaProfile);
  1786.         }
  1787.         g_vertexAnimationProfiler.Clear();
  1788. #endif
  1789. }
  1790.  
  1791. void CharacterManager::UpdateStreaming(int nFullUpdateRoundId, int nFastUpdateRoundId)
  1792. {
  1793.         CRY_PROFILE_FUNCTION(PROFILE_ANIMATION)
  1794.  
  1795.         if (nFastUpdateRoundId >= 0)
  1796.                 m_nStreamUpdateRoundId[0] = static_cast<uint32>(nFastUpdateRoundId);
  1797.         if (nFullUpdateRoundId >= 0)
  1798.                 m_nStreamUpdateRoundId[1] = static_cast<uint32>(nFullUpdateRoundId);
  1799.  
  1800.         if (Console::GetInst().ca_StreamCHR)
  1801.         {
  1802.                 uint32 nRenderFrameId = gEnv->pRenderer->GetFrameID(false);
  1803.                 uint32* nRoundIds = m_nStreamUpdateRoundId;
  1804.  
  1805.                 UpdateStreaming_SKEL(m_arrModelCacheSKEL, nRenderFrameId, nRoundIds);
  1806.                 UpdateStreaming_SKIN(m_arrModelCacheSKIN, nRenderFrameId, nRoundIds);
  1807.  
  1808. #ifdef EDITOR_PCDEBUGCODE
  1809.                 UpdateStreaming_SKEL(m_arrModelCacheSKEL_CharEdit, nRenderFrameId, nRoundIds);
  1810.                 UpdateStreaming_SKIN(m_arrModelCacheSKIN_CharEdit, nRenderFrameId, nRoundIds);
  1811. #endif
  1812.         }
  1813. }
  1814.  
  1815. void CharacterManager::UpdateStreaming_SKEL(std::vector<CDefaultSkeletonReferences>& skels, uint32 nRenderFrameId, const uint32* nRoundIds)
  1816. {
  1817.         for (std::vector<CDefaultSkeletonReferences>::iterator it = skels.begin(), itEnd = skels.end(); it != itEnd; ++it)
  1818.         {
  1819.                 CDefaultSkeleton* pSkel = it->m_pDefaultSkeleton;
  1820.                 if (pSkel->m_ObjectType != CHR)
  1821.                         continue;
  1822.  
  1823.                 CModelMesh* pSkelMesh = pSkel->GetModelMesh();
  1824.                 if (!pSkelMesh)
  1825.                         continue;
  1826.  
  1827.                 MeshStreamInfo& si = pSkelMesh->m_stream;
  1828.                 if (!si.pStreamer)
  1829.                 {
  1830.                         bool bShouldBeInMemRender = si.nFrameId > nRenderFrameId - 4;
  1831.                         bool bShouldBeInMemPrecache = false;
  1832.                         for (int j = 0; j < MAX_STREAM_PREDICTION_ZONES; ++j)
  1833.                                 bShouldBeInMemPrecache = bShouldBeInMemPrecache || (si.nRoundIds[j] >= nRoundIds[j] - 2);
  1834.  
  1835.                         bool bShouldBeInMemRefs = si.nKeepResidentRefs > 0;
  1836.                         bool bShouldBeInMem = bShouldBeInMemRefs || bShouldBeInMemRender || bShouldBeInMemPrecache;
  1837.  
  1838.                         if (bShouldBeInMem)
  1839.                         {
  1840.                                 if (!pSkelMesh->m_pIRenderMesh)
  1841.                                 {
  1842.                                         EStreamTaskPriority estp;
  1843.                                         if (si.bIsUrgent)
  1844.                                                 estp = estpUrgent;
  1845.                                         else if (bShouldBeInMemRefs)
  1846.                                                 estp = estpAboveNormal;
  1847.                                         else
  1848.                                                 estp = estpNormal;
  1849.  
  1850.                                         si.pStreamer = new CryCHRLoader;
  1851.                                         si.pStreamer->BeginLoadCHRRenderMesh(pSkel, it->m_RefByInstances, estp);
  1852.                                 }
  1853.                         }
  1854.                         else if (pSkelMesh->m_pIRenderMesh)
  1855.                         {
  1856.                                 pSkelMesh->m_pIRenderMesh = NULL;
  1857.                         }
  1858.  
  1859.                         si.bIsUrgent = false;
  1860.                 }
  1861.         }
  1862. }
  1863.  
  1864. void CharacterManager::UpdateStreaming_SKIN(std::vector<CDefaultSkinningReferences>& skins, uint32 nRenderFrameId, const uint32* nRoundIds)
  1865. {
  1866.         for (std::vector<CDefaultSkinningReferences>::iterator it = skins.begin(), itEnd = skins.end(); it != itEnd; ++it)
  1867.         {
  1868.                 CSkin* pSkin = it->m_pDefaultSkinning;
  1869.  
  1870.                 for (int i = 0, c = pSkin->m_arrModelMeshes.size(); i < c; ++i)
  1871.                 {
  1872.                         CModelMesh& mm = pSkin->m_arrModelMeshes[i];
  1873.                         MeshStreamInfo& si = mm.m_stream;
  1874.  
  1875.                         if (!si.pStreamer)
  1876.                         {
  1877.                                 bool bShouldBeInMemRender = si.nFrameId > nRenderFrameId - 4;
  1878.                                 bool bShouldBeInMemPrecache = false;
  1879.                                 for (int j = 0; j < MAX_STREAM_PREDICTION_ZONES; ++j)
  1880.                                         bShouldBeInMemPrecache = bShouldBeInMemPrecache || (si.nRoundIds[j] >= nRoundIds[j] - 2);
  1881.  
  1882.                                 bool bShouldBeInMemRefs = si.nKeepResidentRefs > 0;
  1883.                                 bool bShouldBeInMem = bShouldBeInMemRefs || bShouldBeInMemRender || bShouldBeInMemPrecache;
  1884.  
  1885.                                 if (bShouldBeInMem)
  1886.                                 {
  1887.                                         if (!mm.m_pIRenderMesh)
  1888.                                         {
  1889.                                                 EStreamTaskPriority estp;
  1890.                                                 if (si.bIsUrgent)
  1891.                                                         estp = estpUrgent;
  1892.                                                 else if (bShouldBeInMemRefs)
  1893.                                                         estp = estpAboveNormal;
  1894.                                                 else
  1895.                                                         estp = estpNormal;
  1896.  
  1897.                                                 si.pStreamer = new CryCHRLoader;
  1898.                                                 si.pStreamer->BeginLoadSkinRenderMesh(pSkin, i, estp);
  1899.                                         }
  1900.                                 }
  1901.                                 else if (mm.m_pIRenderMesh)
  1902.                                 {
  1903.                                         CDefaultSkinningReferences* pSkinRef = GetDefaultSkinningReferences(pSkin);
  1904.                                         if (pSkinRef == 0)
  1905.                                                 return;
  1906.                                         uint32 nSkinInstances = pSkinRef->m_RefByInstances.size();
  1907.                                         for (int i = 0; i < nSkinInstances; i++)
  1908.                                         {
  1909.                                                 CAttachmentSKIN* pAttachmentSkin = pSkinRef->m_RefByInstances[i];
  1910.                                                 int guid = pAttachmentSkin->GetGuid();
  1911.  
  1912.                                                 if (guid > 0)
  1913.                                                 {
  1914.                                                         mm.m_pIRenderMesh->ReleaseRemappedBoneIndicesPair(guid);
  1915.                                                 }
  1916.                                         }
  1917.  
  1918.                                         uint32 nVClothInstances = pSkinRef->m_RefByInstancesVCloth.size();
  1919.                                         for (int i = 0; i < nVClothInstances; i++)
  1920.                                         {
  1921.                                                 CAttachmentVCLOTH* pAttachmentVCloth = pSkinRef->m_RefByInstancesVCloth[i];
  1922.                                                 int guid = pAttachmentVCloth->GetGuid();
  1923.  
  1924.                                                 if (guid > 0)
  1925.                                                 {
  1926.                                                         if (pAttachmentVCloth->m_pSimSkin)
  1927.                                                         {
  1928.                                                                 IRenderMesh* pVCSimRenderMesh = pAttachmentVCloth->m_pSimSkin->GetIRenderMesh(0);
  1929.                                                                 if (pVCSimRenderMesh && (pVCSimRenderMesh == mm.m_pIRenderMesh))
  1930.                                                                 {
  1931.                                                                         pVCSimRenderMesh->ReleaseRemappedBoneIndicesPair(guid);
  1932.                                                                 }
  1933.                                                         }
  1934.  
  1935.                                                         if (pAttachmentVCloth->m_pRenderSkin)
  1936.                                                         {
  1937.                                                                 IRenderMesh* pVCRenderMesh = pAttachmentVCloth->m_pRenderSkin->GetIRenderMesh(0);
  1938.                                                                 if (pVCRenderMesh && (pVCRenderMesh == mm.m_pIRenderMesh))
  1939.                                                                 {
  1940.                                                                         pVCRenderMesh->ReleaseRemappedBoneIndicesPair(guid);
  1941.                                                                 }
  1942.                                                         }
  1943.                                                 }
  1944.                                         }
  1945.  
  1946.                                         mm.m_pIRenderMesh = NULL;
  1947.                                 }
  1948.  
  1949.                                 si.bIsUrgent = false;
  1950.                         }
  1951.                 }
  1952.         }
  1953. }
  1954.  
  1955. //----------------------------------------------------------------------
  1956. CDefaultSkeleton* CharacterManager::GetModelByAimPoseID(uint32 nGlobalIDAimPose)
  1957. {
  1958.         uint32 numModels = m_arrModelCacheSKEL.size();
  1959.         for (uint32 m = 0; m < numModels; m++)
  1960.         {
  1961.                 CDefaultSkeleton* pModelBase = m_arrModelCacheSKEL[m].m_pDefaultSkeleton;
  1962.                 const char* strFilePath = pModelBase->GetModelFilePath();
  1963.                 const char* fileExt = PathUtil::GetExt(strFilePath);
  1964.                 uint32 isSKEL = stricmp(fileExt, CRY_SKEL_FILE_EXT) == 0;
  1965.                 if (isSKEL)
  1966.                 {
  1967.                         CDefaultSkeleton* pDefaultSkeleton = (CDefaultSkeleton*)pModelBase;
  1968.                         if (pDefaultSkeleton->m_ObjectType == CHR)
  1969.                         {
  1970.                                 const char* PathName = pDefaultSkeleton->GetModelFilePath();
  1971.                                 CAnimationSet* pAnimationSet = pDefaultSkeleton->m_pAnimationSet;
  1972.                                 int32 status = pAnimationSet->FindAimposeByGlobalID(nGlobalIDAimPose);
  1973.                                 if (status > 0)
  1974.                                         return pDefaultSkeleton;
  1975.                         }
  1976.                 }
  1977.         }
  1978.  
  1979. #ifdef EDITOR_PCDEBUGCODE
  1980.         uint32 numModels2 = m_arrModelCacheSKEL_CharEdit.size();
  1981.         for (uint32 m = 0; m < numModels2; m++)
  1982.         {
  1983.                 CDefaultSkeleton* pModelBase = m_arrModelCacheSKEL_CharEdit[m].m_pDefaultSkeleton;
  1984.                 const char* strFilePath = pModelBase->GetModelFilePath();
  1985.                 const char* fileExt = PathUtil::GetExt(strFilePath);
  1986.                 uint32 isSKEL = stricmp(fileExt, CRY_SKEL_FILE_EXT) == 0;
  1987.                 if (isSKEL)
  1988.                 {
  1989.                         CDefaultSkeleton* pDefaultSkeleton = (CDefaultSkeleton*)pModelBase;
  1990.                         if (pDefaultSkeleton->m_ObjectType == CHR)
  1991.                         {
  1992.                                 const char* PathName = pDefaultSkeleton->GetModelFilePath();
  1993.                                 CAnimationSet* pAnimationSet = pDefaultSkeleton->m_pAnimationSet;
  1994.                                 int32 status = pAnimationSet->FindAimposeByGlobalID(nGlobalIDAimPose);
  1995.                                 if (status > 0)
  1996.                                         return pDefaultSkeleton;
  1997.                         }
  1998.                 }
  1999.         }
  2000. #endif
  2001.  
  2002.         return 0;
  2003. }
  2004.  
  2005. void CharacterManager::ReloadAllCHRPARAMS()
  2006. {
  2007. #ifdef EDITOR_PCDEBUGCODE
  2008.         StopAnimationsOnAllInstances();
  2009.         ClearPoseModifiersFromSynchQueue();
  2010.         SyncAllAnimations();
  2011.         Console::GetInst().ca_ReloadAllCHRPARAMS = 0;
  2012.  
  2013.         uint32 numModels = m_arrModelCacheSKEL.size();
  2014.         for (uint32 m = 0; m < numModels; m++)
  2015.         {
  2016.                 CDefaultSkeleton* pDefaultSkeleton = m_arrModelCacheSKEL[m].m_pDefaultSkeleton;
  2017.  
  2018.                 string paramFileNameBase(pDefaultSkeleton->GetModelFilePath());
  2019.                 paramFileNameBase.replace(".chr", ".chrparams");
  2020.                 paramFileNameBase.replace(".cga", ".chrparams");
  2021.  
  2022.                 if (g_pIPak->IsFileExist(paramFileNameBase))
  2023.                 {
  2024.                         g_pCharacterManager->GetParamLoader().ClearLists();
  2025.                         pDefaultSkeleton->m_pAnimationSet->ReleaseAnimationData();
  2026.  
  2027.                         CryLog("Reloading %s", paramFileNameBase.c_str());
  2028.  
  2029.                         CryLogAlways("CryAnimation: Reloading CHRPARAMS for model: %s", pDefaultSkeleton->GetModelFilePath());
  2030.                         pDefaultSkeleton->m_pAnimationSet->NotifyListenersAboutReloadStarted();
  2031.                         pDefaultSkeleton->LoadCHRPARAMS(paramFileNameBase.c_str());
  2032.                         pDefaultSkeleton->m_pAnimationSet->NotifyListenersAboutReload();
  2033.                 }
  2034.         }
  2035.  
  2036.         uint32 numModelsCharEdit = m_arrModelCacheSKEL_CharEdit.size();
  2037.         for (uint32 m = 0; m < numModelsCharEdit; m++)
  2038.         {
  2039.                 CDefaultSkeleton* pDefaultSkeleton = m_arrModelCacheSKEL_CharEdit[m].m_pDefaultSkeleton;
  2040.  
  2041.                 string paramFileNameBase(pDefaultSkeleton->GetModelFilePath());
  2042.                 paramFileNameBase.replace(".chr", ".chrparams");
  2043.                 paramFileNameBase.replace(".cga", ".chrparams");
  2044.  
  2045.                 if (g_pIPak->IsFileExist(paramFileNameBase))
  2046.                 {
  2047.                         g_pCharacterManager->GetParamLoader().ClearLists();
  2048.                         pDefaultSkeleton->m_pAnimationSet->ReleaseAnimationData();
  2049.  
  2050.                         CryLog("Reloading %s", paramFileNameBase.c_str());
  2051.  
  2052.                         CryLogAlways("CryAnimation: Reloading CHRPARAMS for model: %s", pDefaultSkeleton->GetModelFilePath());
  2053.                         pDefaultSkeleton->m_pAnimationSet->NotifyListenersAboutReloadStarted();
  2054.                         pDefaultSkeleton->LoadCHRPARAMS(paramFileNameBase.c_str());
  2055.                         pDefaultSkeleton->m_pAnimationSet->NotifyListenersAboutReload();
  2056.                 }
  2057.         }
  2058.  
  2059. #endif
  2060. }
  2061.  
  2062. void CharacterManager::TrackMemoryOfModels()
  2063. {
  2064. #ifndef _RELEASE
  2065.         uint32 tmp = Console::GetInst().ca_DebugModelCache;
  2066.         Console::GetInst().ca_DebugModelCache = 7;
  2067.         DebugModelCache(0, m_arrModelCacheSKEL, m_arrModelCacheSKIN);
  2068.         Console::GetInst().ca_DebugModelCache = tmp;
  2069. #endif
  2070. }
  2071.  
  2072. void CharacterManager::DebugModelCache(uint32 printtxt, std::vector<CDefaultSkeletonReferences>& parrModelCacheSKEL, std::vector<CDefaultSkinningReferences>& parrModelCacheSKIN)
  2073. {
  2074.         float fWhite[4] = { 1, 1, 1, 1 };
  2075.         m_AnimationManager.m_AnimMemoryTracker.m_numTCharInstances = 0;
  2076.         m_AnimationManager.m_AnimMemoryTracker.m_nTotalCharMemory = 0;
  2077.         m_AnimationManager.m_AnimMemoryTracker.m_numModels = 0;
  2078.  
  2079.         uint32 nTotalModelMemory = 0;
  2080.         uint32 nTotalModelSkeletonMemory = 0;
  2081.         uint32 nTotalModelPhysics = 0;
  2082.         uint32 nTotalUsedPhysics = 0;
  2083.         uint32 nTotalModelAnimationSet = 0;
  2084.         uint32 nTotalAttachmentMemory = 0;
  2085.         uint32 nTotalAttachmentCount = 0;
  2086.  
  2087.         uint32 nPrintFlags = Console::GetInst().ca_DebugModelCache;
  2088.         if (nPrintFlags & 1)
  2089.         {
  2090.                 uint32 nTotalSkelMemory = 0;
  2091.                 uint32 nTotalSkeletonMemory = 0;
  2092.                 uint32 numTSkelInstances = 0;
  2093.  
  2094.                 uint32 numModelSKELs = parrModelCacheSKEL.size();
  2095.                 g_pAuxGeom->Draw2dLabel(1, g_YLine, 2.0f, fWhite, false, "arrModelCacheSKEL: %4d", numModelSKELs), g_YLine += 20.0f;
  2096.                 for (uint32 m = 0; m < numModelSKELs; m++)
  2097.                 {
  2098.                         CDefaultSkeleton* pDefaultSkeleton = parrModelCacheSKEL[m].m_pDefaultSkeleton;
  2099.                         if (pDefaultSkeleton->m_pCGA_Object)
  2100.                                 continue;
  2101.                         uint32 numSkelInstances = parrModelCacheSKEL[m].m_RefByInstances.size();
  2102.                         uint32 nRefCounter = pDefaultSkeleton->GetRefCounter();
  2103.                         numTSkelInstances += numSkelInstances;
  2104.                         uint32 numAnims = pDefaultSkeleton->m_pAnimationSet->GetAnimationCount();
  2105.                         uint32 nIMemory = 0;
  2106.                         for (uint32 i = 0; i < numSkelInstances; i++)
  2107.                         {
  2108.                                 CCharInstance* pCharInstance = parrModelCacheSKEL[m].m_RefByInstances[i];
  2109.                                 nTotalSkelMemory += pCharInstance->SizeOfCharInstance();
  2110.                                 nTotalAttachmentMemory += pCharInstance->m_AttachmentManager.SizeOfAllAttachments();
  2111.                                 nTotalAttachmentCount += pCharInstance->m_AttachmentManager.GetAttachmentCount();
  2112.                                 nIMemory += pCharInstance->SizeOfCharInstance();
  2113.                         }
  2114.  
  2115.                         nTotalModelMemory += pDefaultSkeleton->SizeOfDefaultSkeleton();
  2116.                         nTotalModelSkeletonMemory += pDefaultSkeleton->SizeOfSkeleton();
  2117.                         nTotalModelAnimationSet += pDefaultSkeleton->m_pAnimationSet->SizeOfAnimationSet();
  2118.                         if (printtxt)
  2119.                         {
  2120.                                 float fColor[4] = { 0, 1, 0, 1 };
  2121.                                 const char* PathName = pDefaultSkeleton->GetModelFilePath();
  2122.                                 uint32 nKiM = pDefaultSkeleton->GetKeepInMemory();
  2123.                                 uint32 nMMemory = pDefaultSkeleton->SizeOfDefaultSkeleton();
  2124.                                 if ((nPrintFlags & 0x10) == 0)
  2125.                                 {
  2126.                                         g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.3f, fColor, false, "Model: %3d   SkelInst: %2d  RefCount: %2d imem: %7d  mmem: %7d anim: %4d  KiM: %2d %s", m, numSkelInstances, nRefCounter, nIMemory, nMMemory, numAnims, nKiM, PathName),
  2127.                                         g_YLine += 16.0f;
  2128.                                 }
  2129.                                 if (nPrintFlags & 0x8)
  2130.                                 {
  2131.                                         CryLogAlways("Model: %3u   SkelInst: %2u  RefCount: %2u  imem: %7u  mmem: %7u anim: %4u  KiM: %2u %s", m, numSkelInstances, nRefCounter, nIMemory, nMMemory, numAnims, nKiM, PathName), g_YLine += 16.0f;
  2132.                                 }
  2133.                         }
  2134.                 }
  2135.                 float fColorRed[4] = { 1, 0, 0, 1 };
  2136.                 g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.6f, fColorRed, false, "SKELInstancesCounter:%3d (Mem: %4dKB)     ModelsCounter:%3d (Mem: %4dKB)", numTSkelInstances, nTotalSkelMemory / 1024, numModelSKELs, nTotalModelMemory / 1024);
  2137.                 g_YLine += 32.0f;
  2138.                 if (nPrintFlags & 0x8)
  2139.                 {
  2140.                         CryLogAlways("SKELInstancesCounter:%3u (Mem: %4uKB)     ModelsCounter:%3u (Mem: %4uKB)", numTSkelInstances, nTotalSkelMemory / 1024, numModelSKELs, nTotalModelMemory / 1024), g_YLine += 16.0f;
  2141.                 }
  2142.  
  2143.                 m_AnimationManager.m_AnimMemoryTracker.m_numTCharInstances += numTSkelInstances;
  2144.                 m_AnimationManager.m_AnimMemoryTracker.m_nTotalCharMemory += nTotalSkelMemory;
  2145.                 m_AnimationManager.m_AnimMemoryTracker.m_numModels += numModelSKELs;
  2146.         }
  2147.  
  2148.         //-----------------------------------------------------------------------------------------------------------------------------
  2149.         if (nPrintFlags & 2)
  2150.         {
  2151.                 uint32 nTotalSkelMemory = 0;
  2152.                 uint32 numTSkelInstances = 0;
  2153.                 uint32 numModelSKELs = parrModelCacheSKEL.size();
  2154.                 for (uint32 m = 0; m < numModelSKELs; m++)
  2155.                 {
  2156.                         CDefaultSkeleton* pDefaultSkeleton = parrModelCacheSKEL[m].m_pDefaultSkeleton;
  2157.                         if (pDefaultSkeleton->m_pCGA_Object == 0)
  2158.                                 continue;
  2159.                         uint32 numSkelInstances = parrModelCacheSKEL[m].m_RefByInstances.size();
  2160.                         uint32 nRefCounter = pDefaultSkeleton->GetRefCounter();
  2161.                         numTSkelInstances += numSkelInstances;
  2162.                         uint32 numAnims = pDefaultSkeleton->m_pAnimationSet->GetAnimationCount();
  2163.                         uint32 nIMemory = 0;
  2164.                         for (uint32 i = 0; i < numSkelInstances; i++)
  2165.                         {
  2166.                                 CCharInstance* pCharInstance = parrModelCacheSKEL[m].m_RefByInstances[i];
  2167.                                 nTotalSkelMemory += pCharInstance->SizeOfCharInstance();
  2168.                                 nTotalAttachmentMemory += pCharInstance->m_AttachmentManager.SizeOfAllAttachments();
  2169.                                 nTotalAttachmentCount += pCharInstance->m_AttachmentManager.GetAttachmentCount();
  2170.                                 nIMemory += pCharInstance->SizeOfCharInstance();
  2171.                         }
  2172.  
  2173.                         nTotalModelMemory += pDefaultSkeleton->SizeOfDefaultSkeleton();
  2174.                         nTotalModelSkeletonMemory += pDefaultSkeleton->SizeOfSkeleton();
  2175.                         nTotalModelAnimationSet += pDefaultSkeleton->m_pAnimationSet->SizeOfAnimationSet();
  2176.                         if (printtxt)
  2177.                         {
  2178.                                 float fColor[4] = { 0, 1, 0, 1 };
  2179.                                 const char* PathName = pDefaultSkeleton->GetModelFilePath();
  2180.                                 uint32 nKiM = pDefaultSkeleton->GetKeepInMemory();
  2181.                                 uint32 nMMemory = pDefaultSkeleton->SizeOfDefaultSkeleton();
  2182.                                 if ((nPrintFlags & 0x10) == 0)
  2183.                                         g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.3f, fColor, false, "Model: %3d   SkelInst: %2d  RefCount: %2d imem: %7d  mmem: %7d anim: %4d  Kim: %2d %s", m, numSkelInstances, nRefCounter, nIMemory, nMMemory, numAnims, nKiM, PathName), g_YLine += 16.0f;
  2184.                                 if (nPrintFlags & 0x08)
  2185.                                         CryLogAlways("Model: %3u   SkelInst: %2u  RefCount: %2u  imem: %7u  mmem: %7u anim: %4u  KiM: %2u %s", m, numSkelInstances, nRefCounter, nIMemory, nMMemory, numAnims, nKiM, PathName), g_YLine += 16.0f;
  2186.                         }
  2187.                 }
  2188.                 float fColorRed[4] = { 1, 0, 0, 1 };
  2189.                 g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.6f, fColorRed, false, "SKELInstancesCounter:%3d (Mem: %4dKB)     ModelsCounter:%3d (Mem: %4dKB)", numTSkelInstances, nTotalSkelMemory / 1024, numModelSKELs, nTotalModelMemory / 1024);
  2190.                 g_YLine += 32.0f;
  2191.                 if (nPrintFlags & 0x08)
  2192.                         CryLogAlways("SKELInstancesCounter:%3u (Mem: %4uKB)     ModelsCounter:%3u (Mem: %4uKB)", numTSkelInstances, nTotalSkelMemory / 1024, numModelSKELs, nTotalModelMemory / 1024), g_YLine += 16.0f;
  2193.                 m_AnimationManager.m_AnimMemoryTracker.m_numTCharInstances += numTSkelInstances;
  2194.                 m_AnimationManager.m_AnimMemoryTracker.m_nTotalCharMemory += nTotalSkelMemory;
  2195.                 m_AnimationManager.m_AnimMemoryTracker.m_numModels += numModelSKELs;
  2196.         }
  2197.  
  2198.         //-----------------------------------------------------------------------------------------------------------------------------
  2199.  
  2200.         if (nPrintFlags & 4)
  2201.         {
  2202.                 uint32 nTotalSkinMemory = 0;
  2203.                 uint32 numTSkinInstances = 0;
  2204.                 uint32 numModelSKINs = parrModelCacheSKIN.size();
  2205.                 g_pAuxGeom->Draw2dLabel(1, g_YLine, 2.0f, fWhite, false, "arrModelCacheSKIN: %4d", numModelSKINs), g_YLine += 20.0f;
  2206.                 for (uint32 m = 0; m < numModelSKINs; m++)
  2207.                 {
  2208.                         CSkin* pModelSKIN = parrModelCacheSKIN[m].m_pDefaultSkinning;
  2209.                         uint32 nRefCounter = pModelSKIN->GetRefCounter();
  2210.                         uint32 numSkinInstances = parrModelCacheSKIN[m].m_RefByInstances.size();
  2211.                         numTSkinInstances += numSkinInstances;
  2212.                         uint32 nIMemory = 0;
  2213.                         for (uint32 i = 0; i < numSkinInstances; i++)
  2214.                         {
  2215.                                 CAttachmentSKIN* pSkinInstance = parrModelCacheSKIN[m].m_RefByInstances[i];
  2216.                                 nIMemory += pSkinInstance->SizeOfThis();
  2217.                                 nTotalSkinMemory += pSkinInstance->SizeOfThis();
  2218.                         }
  2219.                         uint32 numVClothInstances = parrModelCacheSKIN[m].m_RefByInstancesVCloth.size();
  2220.                         numTSkinInstances += numVClothInstances;
  2221.                         for (uint32 i = 0; i < numVClothInstances; i++)
  2222.                         {
  2223.                                 CAttachmentVCLOTH* pVClothInstance = parrModelCacheSKIN[m].m_RefByInstancesVCloth[i];
  2224.                                 nIMemory += pVClothInstance->SizeOfThis();
  2225.                                 nTotalSkinMemory += pVClothInstance->SizeOfThis();
  2226.                         }
  2227.  
  2228.                         nTotalModelMemory += pModelSKIN->SizeOfModelData();
  2229.                         if (printtxt)
  2230.                         {
  2231.                                 const char* PathName = pModelSKIN->GetModelFilePath();
  2232.  
  2233.                                 uint32 numLODs = pModelSKIN->GetNumLODs();
  2234.                                 uint32 nKiM = pModelSKIN->GetKeepInMemory();
  2235.  
  2236.                                 uint32 nMMemory = pModelSKIN->SizeOfModelData();
  2237.                                 float fColor[4] = { 0, 0.5f, 0, 0.7f };
  2238.                                 if ((nPrintFlags & 0x10) == 0)
  2239.                                         g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.3f, fColor, false, "Model: %3d   SkinInst: %2d  RefCount: %2d imem: %7d  mmem: %7d  LOD: %2d KiM: %2d  %s", m, numSkinInstances + numVClothInstances, nRefCounter, nIMemory, nMMemory, numLODs, nKiM, PathName), g_YLine += 16.0f;
  2240.                                 if (nPrintFlags & 0x08)
  2241.                                         CryLogAlways("Model: %3u   SkinInst: %2u  RefCount: %2u imem: %7u  mmem: %7u  LOD: %2u KiM: %2u %s", m, numSkinInstances + numVClothInstances, nRefCounter, nIMemory, nMMemory, numLODs, nKiM, PathName), g_YLine += 16.0f;
  2242.                         }
  2243.                 }
  2244.                 float fColorRed[4] = { 1, 0, 0, 1 };
  2245.                 g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.6f, fColorRed, false, "SKINInstancesCounter:%3d (Mem: %4dKB)     ModelsCounter:%3d (Mem: %4dKB)", numTSkinInstances, nTotalSkinMemory / 1024, numModelSKINs, nTotalModelMemory / 1024);
  2246.                 g_YLine += 32.0f;
  2247.                 m_AnimationManager.m_AnimMemoryTracker.m_numTSkinInstances = numTSkinInstances;
  2248.                 m_AnimationManager.m_AnimMemoryTracker.m_nTotalSkinMemory = nTotalSkinMemory;
  2249.         }
  2250.  
  2251.         //-----------------------------------------------------------------------------------------------------------------------------
  2252.  
  2253.         if (printtxt)
  2254.         {
  2255.                 float fColorRed[4] = { 1, 0, 0, 1 };
  2256.                 g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.6f, fColorRed, false, "-----------------------------------------------------------------------------------------");
  2257.                 g_YLine += 16.0f;
  2258.  
  2259.                 g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.6f, fColorRed, false, "nTotalAttachmentMemory:  %4dKB  nTotalAttachmentCount:  %4dKB", nTotalAttachmentMemory / 1024, nTotalAttachmentCount);
  2260.                 g_YLine += 32.0f;
  2261.  
  2262.                 g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.6f, fColorRed, false, "nAnimationSet:  %4dKB", nTotalModelAnimationSet / 1024);
  2263.                 g_YLine += 16.0f;
  2264.                 if (nPrintFlags & 0x08)
  2265.                         CryLogAlways("nAnimationSet:  %4uKB", nTotalModelAnimationSet / 1024);
  2266.  
  2267.                 g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.6f, fColorRed, false, "nTotalModelSkeletonMemory:  %4dKB     nTotalModelPhysics: %4dKB   nUsedPhysics: %4dKB   nEmptyPhysics: %4dKB", nTotalModelSkeletonMemory / 1024, nTotalModelPhysics / 1024, nTotalUsedPhysics / 1024, nTotalModelPhysics / 1024 - nTotalUsedPhysics / 1024);
  2268.                 g_YLine += 16.0f;
  2269.                 if (nPrintFlags & 0x08)
  2270.                         CryLogAlways("nTotalModelSkeletonMemory:  %4uKB     nTotalModelPhysics: %4uKB   nUsedPhysics: %4uKB   nEmptyPhysics: %4uKB", nTotalModelSkeletonMemory / 1024, nTotalModelPhysics / 1024, nTotalUsedPhysics / 1024, nTotalModelPhysics / 1024 - nTotalUsedPhysics / 1024);
  2271.  
  2272.                 g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.6f, fColorRed, false, "TotalModelMemory (Mem: %4dKB)", nTotalModelMemory / 1024);
  2273.                 g_YLine += 32.0f;
  2274.         }
  2275.  
  2276.         m_AnimationManager.m_AnimMemoryTracker.m_nTotalMMemory = nTotalModelMemory;
  2277. }
  2278.  
  2279. //---------------------------------
  2280. //just for reloading
  2281. CAnimationSet* CharacterManager::GetAnimationSetUsedInCharEdit()
  2282. {
  2283. #ifdef EDITOR_PCDEBUGCODE
  2284.         uint32 numModels = m_arrModelCacheSKEL_CharEdit.size();
  2285.         for (uint32 m = 0; m < numModels; m++)
  2286.         {
  2287.                 float fColor[4] = { 0, 1, 0, 1 };
  2288.                 CDefaultSkeleton* pDefaultSkeleton = m_arrModelCacheSKEL_CharEdit[m].m_pDefaultSkeleton;
  2289.                 const char* strFilepath = pDefaultSkeleton->GetModelFilePath();
  2290.                 const char* fileExt = PathUtil::GetExt(strFilepath);
  2291.                 uint32 isSKEL = stricmp(fileExt, CRY_SKEL_FILE_EXT) == 0;
  2292.                 if (!isSKEL)
  2293.                         continue;
  2294.  
  2295.                 uint32 numInstances = m_arrModelCacheSKEL_CharEdit[m].m_RefByInstances.size();
  2296.                 for (uint32 i = 0; i < numInstances; i++)
  2297.                 {
  2298.                         CCharInstance* pCharInstance = m_arrModelCacheSKEL_CharEdit[m].m_RefByInstances[i];
  2299.                         if (pCharInstance->GetCharEditMode())
  2300.                         {
  2301.                                 CDefaultSkeleton* pInstModel = pCharInstance->m_pDefaultSkeleton;
  2302.                                 if (pDefaultSkeleton != pInstModel)
  2303.                                         CryFatalError("CryAnimation: mem corruption");
  2304.                                 return (CAnimationSet*)pInstModel->GetIAnimationSet();
  2305.                         }
  2306.                 }
  2307.         }
  2308. #endif
  2309.  
  2310.         return 0;
  2311. }
  2312.  
  2313. void CharacterManager::StopAnimationsOnAllInstances()
  2314. {
  2315.         InternalStopAnimationsOnAllInstances(nullptr);
  2316. }
  2317.  
  2318. void CharacterManager::StopAnimationsOnAllInstances(const IAnimationSet& animationSet)
  2319. {
  2320.         InternalStopAnimationsOnAllInstances(&animationSet);
  2321. }
  2322.  
  2323. void CharacterManager::InternalStopAnimationsOnAllInstances(const IAnimationSet* pAnimationSet)
  2324. {
  2325.         uint32 numModels = m_arrModelCacheSKEL.size();
  2326.         for (uint32 m = 0; m < numModels; m++)
  2327.         {
  2328.                 CDefaultSkeleton* pDefaultSkeleton = m_arrModelCacheSKEL[m].m_pDefaultSkeleton;
  2329.                 if (pAnimationSet && (pDefaultSkeleton->GetIAnimationSet() != pAnimationSet))
  2330.                         continue;
  2331.  
  2332.                 const char* strFilepath = pDefaultSkeleton->GetModelFilePath();
  2333.                 const char* fileExt = PathUtil::GetExt(strFilepath);
  2334.                 uint32 isSKEL = stricmp(fileExt, CRY_SKEL_FILE_EXT) == 0;
  2335.                 if (isSKEL == 0)
  2336.                         continue;
  2337.  
  2338.                 uint32 numInstances = m_arrModelCacheSKEL[m].m_RefByInstances.size();
  2339.                 for (uint32 i = 0; i < numInstances; i++)
  2340.                 {
  2341.                         CCharInstance* pCharInstance = m_arrModelCacheSKEL[m].m_RefByInstances[i];
  2342.                         pCharInstance->m_SkeletonAnim.StopAnimationsAllLayers();
  2343.                         pCharInstance->m_SkeletonAnim.FinishAnimationComputations();
  2344.                 }
  2345.         }
  2346.  
  2347. #ifdef EDITOR_PCDEBUGCODE
  2348.         uint32 numModelsCharEdit = m_arrModelCacheSKEL_CharEdit.size();
  2349.         for (uint32 m = 0; m < numModelsCharEdit; m++)
  2350.         {
  2351.                 CDefaultSkeleton* pDefaultSkeleton = m_arrModelCacheSKEL_CharEdit[m].m_pDefaultSkeleton;
  2352.                 if (pAnimationSet && (pDefaultSkeleton->GetIAnimationSet() != pAnimationSet))
  2353.                         continue;
  2354.  
  2355.                 const char* strFilepath = pDefaultSkeleton->GetModelFilePath();
  2356.                 const char* fileExt = PathUtil::GetExt(strFilepath);
  2357.                 uint32 isSKEL = stricmp(fileExt, CRY_SKEL_FILE_EXT) == 0;
  2358.                 if (isSKEL == 0)
  2359.                         continue;
  2360.  
  2361.                 uint32 numInstances = m_arrModelCacheSKEL_CharEdit[m].m_RefByInstances.size();
  2362.                 for (uint32 i = 0; i < numInstances; i++)
  2363.                 {
  2364.                         CCharInstance* pCharInstance = m_arrModelCacheSKEL_CharEdit[m].m_RefByInstances[i];
  2365.                         pCharInstance->m_SkeletonAnim.StopAnimationsAllLayers();
  2366.                         pCharInstance->m_SkeletonAnim.FinishAnimationComputations();
  2367.                 }
  2368.         }
  2369. #endif
  2370.  
  2371.         uint32 numLMGs = g_AnimationManager.m_arrGlobalLMG.size();
  2372.         for (uint32 l = 0; l < numLMGs; l++)
  2373.         {
  2374.                 GlobalAnimationHeaderLMG& rLMG = g_AnimationManager.m_arrGlobalLMG[l];
  2375.                 rLMG.m_DimPara[0].m_nInitialized = 0;
  2376.                 rLMG.m_DimPara[1].m_nInitialized = 0;
  2377.                 rLMG.m_DimPara[2].m_nInitialized = 0;
  2378.                 rLMG.m_DimPara[3].m_nInitialized = 0;
  2379.         }
  2380.  
  2381.         ClearPoseModifiersFromSynchQueue();
  2382.         SyncAllAnimations();
  2383. }
  2384.  
  2385. //---------------------------------------------------------------------------------------------------------------
  2386. //---------------------------------------------------------------------------------------------------------------
  2387. //---------------------------------------------------------------------------------------------------------------
  2388. void CharacterManager::DatabaseUnloading()
  2389. {
  2390.         if (Console::GetInst().ca_DisableAnimationUnloading)
  2391.                 return;
  2392.  
  2393.         uint32 numHeadersCAF = g_AnimationManager.m_arrGlobalCAF.size();
  2394.         if (numHeadersCAF == 0)
  2395.                 return;
  2396.         uint32 numHeadersDBA = g_AnimationManager.m_arrGlobalHeaderDBA.size();
  2397.         if (numHeadersDBA == 0)
  2398.                 return;
  2399.  
  2400.         GlobalAnimationHeaderCAF* parrGlobalCAF = &g_AnimationManager.m_arrGlobalCAF[0];
  2401.         CGlobalHeaderDBA* parrGlobalDBA = &g_AnimationManager.m_arrGlobalHeaderDBA[0];
  2402.  
  2403.         uint32 s = m_StartGAH_Iterator;
  2404.         uint32 e = min(numHeadersCAF, m_StartGAH_Iterator + 100);
  2405.  
  2406.         if (s == 0)
  2407.         {
  2408.                 for (uint32 d = 0; d < numHeadersDBA; d++)
  2409.                         parrGlobalDBA[d].m_nUsedAnimations = 0;
  2410.         }
  2411.  
  2412.         for (uint32 i = s; i < e; i++)
  2413.         {
  2414.                 if (parrGlobalCAF[i].m_nRef_at_Runtime == 0)
  2415.                 {
  2416.                         if (parrGlobalCAF[i].IsAssetOnDemand() && parrGlobalCAF[i].IsAssetLoaded())
  2417.                                 g_AnimationManager.UnloadAnimationCAF(parrGlobalCAF[i]);
  2418.                         continue;
  2419.                 }
  2420.                 uint32 nCRC32 = parrGlobalCAF[i].m_FilePathDBACRC32;
  2421.                 if (nCRC32)
  2422.                 {
  2423.                         for (uint32 d = 0; d < numHeadersDBA; d++)
  2424.                         {
  2425.                                 if (nCRC32 == parrGlobalDBA[d].m_FilePathDBACRC32)
  2426.                                 {
  2427.                                         parrGlobalDBA[d].m_nUsedAnimations++;
  2428.                                         parrGlobalDBA[d].m_nLastUsedTimeDelta = 0;
  2429.                                 }
  2430.                         }
  2431.                 }
  2432.         }
  2433.  
  2434.         m_StartGAH_Iterator += 100;
  2435.         if (m_StartGAH_Iterator < numHeadersCAF)
  2436.                 return;
  2437.  
  2438.         //----------------------------------------------------------------------------------------------------
  2439.  
  2440.         m_StartGAH_Iterator = 0;
  2441.         float fColor[4] = { 1, 0, 0, 1 };
  2442.         //      g_pAuxGeom->Draw2dLabel( 1,g_YLine, 1.2f, fColor, false,"DatabaseUnloading");
  2443.         //      g_YLine+=12.0f;
  2444.  
  2445.         uint32 timeDelta = GetDatabaseUnloadTimeDelta();
  2446.  
  2447.         for (uint32 d = 0; d < numHeadersDBA; d++)
  2448.         {
  2449.                 CGlobalHeaderDBA& rGHDBA = g_AnimationManager.m_arrGlobalHeaderDBA[d];
  2450.                 if (rGHDBA.m_pDatabaseInfo == 0)
  2451.                         continue;
  2452.  
  2453.                 const char* pName = rGHDBA.m_strFilePathDBA;
  2454.                 uint32 nDBACRC32 = rGHDBA.m_FilePathDBACRC32;
  2455.                 if (rGHDBA.m_nUsedAnimations || rGHDBA.m_bDBALock)
  2456.                 {
  2457.                         rGHDBA.m_nLastUsedTimeDelta = 0;
  2458.                         continue;
  2459.                 }
  2460.  
  2461.                 rGHDBA.m_nLastUsedTimeDelta += timeDelta;
  2462.  
  2463.                 if (rGHDBA.m_nLastUsedTimeDelta <= (uint32) Console::GetInst().ca_DBAUnloadUnregisterTime * 1000)
  2464.                         continue;
  2465.  
  2466.                 //      g_pAuxGeom->Draw2dLabel( 1,g_YLine, 1.2f, fColor, false,"Scanning: %s",pName );
  2467.                 //      g_YLine+=12.0f;
  2468.  
  2469.                 for (uint32 i = 0; i < numHeadersCAF; i++)
  2470.                 {
  2471.                         GlobalAnimationHeaderCAF& rGAH = g_AnimationManager.m_arrGlobalCAF[i];
  2472.                         if (rGAH.m_FilePathDBACRC32 != nDBACRC32)
  2473.                                 continue;
  2474.                         rGAH.m_nControllers = 0;    //just mark as unloaded
  2475.                 }
  2476.         }
  2477.  
  2478.         //check if the time  has come to remove DBA
  2479.         for (uint32 d = 0; d < numHeadersDBA; d++)
  2480.         {
  2481.                 CGlobalHeaderDBA& rGHDBA = g_AnimationManager.m_arrGlobalHeaderDBA[d];
  2482.                 if (rGHDBA.m_pDatabaseInfo == 0)
  2483.                         continue;
  2484.                 if (rGHDBA.m_nLastUsedTimeDelta <= (uint32) Console::GetInst().ca_DBAUnloadRemoveTime * 1000)
  2485.                         continue;
  2486.                 if (rGHDBA.m_nUsedAnimations)
  2487.                         continue;
  2488. #ifdef _DEBUG
  2489.                 const char* pName = rGHDBA.m_strFilePathDBA;
  2490. #endif
  2491.  
  2492.                 m_AllowStartOfAnimation = 0;
  2493.                 uint32 numModels = m_arrModelCacheSKEL.size();
  2494.                 for (uint32 m = 0; m < numModels; m++)
  2495.                 {
  2496.                         CDefaultSkeleton* pDefaultSkeleton = m_arrModelCacheSKEL[m].m_pDefaultSkeleton;
  2497.                         const char* strFilepath = pDefaultSkeleton->GetModelFilePath();
  2498.                         const char* fileExt = PathUtil::GetExt(strFilepath);
  2499.                         uint32 isSKEL = stricmp(fileExt, CRY_SKEL_FILE_EXT) == 0;
  2500.                         if (isSKEL == 0)
  2501.                                 continue;
  2502.                         uint32 numInstances = m_arrModelCacheSKEL[m].m_RefByInstances.size();
  2503.                         for (uint32 i = 0; i < numInstances; i++)
  2504.                         {
  2505.                                 CCharInstance* pCharInstance = m_arrModelCacheSKEL[m].m_RefByInstances[i];
  2506.                                 pCharInstance->m_SkeletonAnim.FinishAnimationComputations();
  2507.                         }
  2508.                 }
  2509.                 rGHDBA.DeleteDatabaseDBA(); //remove entire DBA from memory
  2510.                 m_AllowStartOfAnimation = 1;
  2511.         }
  2512.  
  2513.         UpdateDatabaseUnloadTimeStamp();
  2514. }
  2515.  
  2516. //////////////////////////////////////////////////////////////////////////
  2517. class CAnimationStatsResourceList
  2518. {
  2519. public:
  2520.         stack_string UnifyFilename(const char* sResourceFile)
  2521.         {
  2522.                 stack_string filename = sResourceFile;
  2523.                 filename.replace('\\', '/');
  2524.                 filename.MakeLower();
  2525.                 return filename;
  2526.         }
  2527.  
  2528.         void Add(const char* sResourceFile)
  2529.         {
  2530.                 stack_string filename = UnifyFilename(sResourceFile);
  2531.                 m_set.insert(filename);
  2532.         }
  2533.         void Remove(const char* sResourceFile)
  2534.         {
  2535.                 stack_string filename = UnifyFilename(sResourceFile);
  2536.                 m_set.erase(filename);
  2537.         }
  2538.         void Clear()
  2539.         {
  2540.                 m_set.clear();
  2541.         }
  2542.         bool IsExist(const char* sResourceFile)
  2543.         {
  2544.                 stack_string filename = UnifyFilename(sResourceFile);
  2545.                 if (m_set.find(filename) != m_set.end())
  2546.                         return true;
  2547.                 return false;
  2548.         }
  2549.         void LoadCAF(const char* sResourceListFilename)
  2550.         {
  2551.                 m_filename = sResourceListFilename;
  2552.                 FILE* file = fxopen(sResourceListFilename, "rb");
  2553.                 if (file)
  2554.                 {
  2555.                         PREFAST_SUPPRESS_WARNING(6031) fseek(file, 0, SEEK_END);
  2556.                         int nFileLentgh = ftell(file);
  2557.                         PREFAST_SUPPRESS_WARNING(6031) fseek(file, 0, SEEK_SET);
  2558.                         char* buf = new char[nFileLentgh + 16];
  2559.                         (void)fread(buf, nFileLentgh, 1, file);
  2560.                         buf[nFileLentgh] = 0;
  2561.  
  2562.                         // Parse file, every line in a file represents a resource filename.
  2563.                         char seps[] = "\r\n";
  2564.                         char* token = strtok(buf, seps);
  2565.                         while (token != NULL)
  2566.                         {
  2567.                                 token += 44;
  2568.                                 Add(token);
  2569.                                 token = strtok(NULL, seps);
  2570.                         }
  2571.                         delete[]buf;
  2572.                 }
  2573.         }
  2574.         void LoadLMG(const char* sResourceListFilename)
  2575.         {