BVB Source Codes

CRYENGINE Show SceneTree.cpp Source code

Return Download CRYENGINE: download SceneTree.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  File name:   SceneTree.cpp
  5. //  Created:     2012 by Vladimir Kajalin.
  6. //  Description: CPU side SVO
  7. // -------------------------------------------------------------------------
  8. //  History:
  9. //
  10. ////////////////////////////////////////////////////////////////////////////
  11.  
  12. #include "StdAfx.h"
  13.  
  14. #if defined(FEATURE_SVO_GI)
  15.  
  16.         #include <Cry3DEngine/ITimeOfDay.h>
  17.         #include "VoxelSegment.h"
  18.         #include "SceneTree.h"
  19.  
  20.         #include "BlockPacker.h"
  21.         #include <CryAnimation/ICryAnimation.h>
  22.         #include "Brush.h"
  23.         #include "SceneTreeManager.h"
  24.         #include <CryRenderer/IRenderAuxGeom.h>
  25.         #include "visareas.h"
  26.  
  27. CSvoEnv* gSvoEnv = 0;
  28.  
  29. template<class T>
  30. struct SThreadSafeTask
  31. {
  32.         SThreadSafeTask(int n)
  33.         {
  34.                 nRequestFrameId = 0;
  35.                 pTaskObject = 0;
  36.         }
  37.         int nRequestFrameId;
  38.         T   pTaskObject;
  39. };
  40.  
  41. template<class T>
  42. struct CTaskConveyor
  43. {
  44.         SThreadSafeArray<SThreadSafeTask<T>, 64>*   pTasks_Compute;
  45.         SThreadSafeArray<SThreadSafeTask<T>, 1024>* pTasks_Store;
  46.         volatile int                                nThreadsCounter;
  47.         bool   nThreadsContinue;
  48.         int    nRequestFrameId;
  49.         string szConveyorName;
  50.  
  51.         struct SThreadInfo
  52.         {
  53.                 CTaskConveyor* pTaskConveyor;
  54.                 int            nThreadSlotId;
  55.         };
  56.  
  57.         SThreadInfo arrThreadInfo[16];
  58.  
  59.         CTaskConveyor(const char* szName)
  60.                 : pTasks_Compute(nullptr)
  61.                 , pTasks_Store(nullptr)
  62.                 , nThreadsCounter(0)
  63.                 , nThreadsContinue(true)
  64.                 , nRequestFrameId(0)
  65.                 , szConveyorName(szName)
  66.                 , arrThreadInfo()
  67.         {
  68.                 Start();
  69.         }
  70.  
  71.         ~CTaskConveyor()
  72.         {
  73.                 Stop();
  74.         }
  75.  
  76.         static void ThreadFunc_Compute(void* pUserData)
  77.         {
  78.                 SThreadInfo* pInf = (SThreadInfo*)pUserData;
  79.                 CTaskConveyor* pTC = pInf->pTaskConveyor;
  80.  
  81.                 CryInterlockedIncrement(&pTC->nThreadsCounter);
  82.  
  83.                 while (pTC->nThreadsContinue)
  84.                 {
  85.                         while (1)
  86.                         {
  87.                                 SThreadSafeTask<T> nextTask = pTC->pTasks_Compute->GetNextTaskFromQeueOrdered2();
  88.  
  89.                                 if (!nextTask.pTaskObject)
  90.                                         break;
  91.  
  92.                                 nextTask.pTaskObject->Task_Compute(pInf->nThreadSlotId);
  93.  
  94.                                 pTC->pTasks_Store->AddNewTaskToQeue(nextTask);
  95.                         }
  96.  
  97.                         CrySleep(1);
  98.                 }
  99.  
  100.                 CryInterlockedDecrement(&pTC->nThreadsCounter);
  101.         }
  102.  
  103.         static void ThreadFunc_Store(void* pUserData)
  104.         {
  105.                 SThreadInfo* pInf = (SThreadInfo*)pUserData;
  106.                 CTaskConveyor* pTC = pInf->pTaskConveyor;
  107.  
  108.                 CryInterlockedIncrement(&pTC->nThreadsCounter);
  109.  
  110.                 while (pTC->nThreadsContinue)
  111.                 {
  112.                         while (1)
  113.                         {
  114.                                 SThreadSafeTask<T> nextTask = pTC->pTasks_Store->GetNextTaskFromQeueOrdered2();
  115.  
  116.                                 if (!nextTask.pTaskObject)
  117.                                         break;
  118.  
  119.                                 nextTask.pTaskObject->Task_Store();
  120.                         }
  121.  
  122.                         CrySleep(1);
  123.                 }
  124.  
  125.                 CryInterlockedDecrement(&pTC->nThreadsCounter);
  126.         }
  127.  
  128.         void Start()
  129.         {
  130.         #if CRY_PLATFORM_WINDOWS && CRY_PLATFORM_64BIT
  131.  
  132.                 pTasks_Compute = new SThreadSafeArray<SThreadSafeTask<T>, 64>;
  133.                 pTasks_Store = new SThreadSafeArray<SThreadSafeTask<T>, 1024>;
  134.  
  135.                 int nThreadSlotId = 0;
  136.  
  137.                 for (; nThreadSlotId < 7; nThreadSlotId++)
  138.                 {
  139.                         arrThreadInfo[nThreadSlotId].pTaskConveyor = this;
  140.                         arrThreadInfo[nThreadSlotId].nThreadSlotId = nThreadSlotId;
  141.                         _beginthread(ThreadFunc_Compute, 0, (void*)&arrThreadInfo[nThreadSlotId]);
  142.                 }
  143.  
  144.                 arrThreadInfo[nThreadSlotId].pTaskConveyor = this;
  145.                 arrThreadInfo[nThreadSlotId].nThreadSlotId = nThreadSlotId;
  146.                 _beginthread(ThreadFunc_Store, 0, (void*)&arrThreadInfo[nThreadSlotId]);
  147.  
  148.                 while (nThreadsCounter < 8)
  149.                         CrySleep(10);
  150.  
  151.         #endif
  152.         }
  153.  
  154.         void Stop()
  155.         {
  156.                 while (pTasks_Compute->Count() || pTasks_Store->Count())
  157.                         CrySleep(10);
  158.                 nThreadsContinue = false;
  159.                 while (nThreadsCounter)
  160.                         CrySleep(10);
  161.                 nThreadsContinue = true;
  162.  
  163.                 T(0)->Task_OnTaskConveyorFinish(); // static
  164.         }
  165.  
  166.         void AddTask(T task, int nTasksAll)
  167.         {
  168.                 SThreadSafeTask<T> nextTask(0);
  169.                 nextTask.pTaskObject = task;
  170.                 nextTask.nRequestFrameId = nRequestFrameId;
  171.  
  172.                 pTasks_Compute->AddNewTaskToQeue(nextTask);
  173.  
  174.                 if (!(nRequestFrameId % 500))
  175.                 {
  176.                         Cry3DEngineBase::PrintMessage("%s: %d of %d tasks processed, pool %d MB of %d MB, compute=%d and store=%d",
  177.                                                       szConveyorName.c_str(),
  178.                                                       nRequestFrameId, nTasksAll, CVoxelSegment::GetBrickPoolUsageLoadedMB(), CVoxelSegment::GetBrickPoolUsageMB(),
  179.                                                       pTasks_Compute->Count(), pTasks_Store->Count());
  180.                 }
  181.  
  182.                 nRequestFrameId++;
  183.         }
  184. };
  185.  
  186. struct SVoxRndDataFileHdr
  187. {
  188.         ETEX_Format nVoxTexFormat;
  189.         uint32      nVoxFlags;
  190. };
  191.  
  192. void CSvoEnv::ReconstructTree(bool bMultiPoint)
  193. {
  194.         char szFolder[256] = "";
  195.         CVoxelSegment::MakeFolderName(szFolder);
  196.         CVoxelSegment::m_strRenderDataFileName = szFolder;
  197.         CVoxelSegment::m_strRenderDataFileName += GLOBAL_CLOUD_MESH_FILE_NAME;
  198.  
  199.         int nNodesCreated = 0;
  200.  
  201.         if (GetCVars()->e_svoTI_Active)
  202.         {
  203.                 PrintMessage("Constructing voxel tree ...");
  204.  
  205.                 m_nVoxTexFormat = eTF_R8G8B8A8;
  206.                 PrintMessage("Voxel texture format: %s", GetRenderer()->GetTextureFormatName(m_nVoxTexFormat));
  207.  
  208.                 SAFE_DELETE(m_pSvoRoot);
  209.                 m_pSvoRoot = new CSvoNode(AABB(Vec3(0, 0, 0), Vec3((float)GetCVars()->e_svoRootSize)), NULL);
  210.                 m_pSvoRoot->AllocateSegment(CVoxelSegment::m_nNextCloudId++, 0, ecss_NotLoaded, ecss_NotLoaded, true);
  211.                 nNodesCreated++;
  212.  
  213.                 //              PrintMessage("Collecting level geometry . . .");
  214.                 //      if(!m_pTree->m_pCloud->m_pNodeTrisXYZ)
  215.                 //      m_pTree->m_pCloud->FindTrianglesForVoxelization(0);
  216.  
  217.                 m_bReady = true;
  218.  
  219.                 CVoxelSegment::CheckAllocateTexturePool();
  220.         }
  221.         else if (FILE* f = fopen(CVoxelSegment::m_strRenderDataFileName, "rb"))
  222.         {
  223.                 PrintMessage("Loading voxel tree ...");
  224.  
  225.                 // read file header
  226.                 SVoxRndDataFileHdr header;
  227.                 fread(&header, 1, sizeof(header), f);
  228.                 m_nVoxTexFormat = header.nVoxTexFormat;
  229.                 if (m_nVoxTexFormat != eTF_BC3 && m_nVoxTexFormat != eTF_R8G8B8A8)
  230.                         m_nVoxTexFormat = eTF_BC3; // old file format
  231.                 PrintMessage("Voxel texture format: %s", GetRenderer()->GetTextureFormatName(m_nVoxTexFormat));
  232.                 fclose(f);
  233.  
  234.                 SAFE_DELETE(m_pSvoRoot);
  235.                 m_pSvoRoot = new CSvoNode(m_worldBox, NULL);
  236.  
  237.                 LoadTree(nNodesCreated);
  238.  
  239.                 CVoxelSegment::CheckAllocateTexturePool();
  240.         }
  241.  
  242.         m_bReady = true;
  243.  
  244.         if (nNodesCreated > 1)
  245.                 PrintMessage("%d tree nodes created", nNodesCreated);
  246. }
  247.  
  248. void CSvoEnv::LoadTree(int& nNodesCreated)
  249. {
  250.         char szFolder[256] = "";
  251.         CVoxelSegment::MakeFolderName(szFolder);
  252.         string filespec = szFolder;
  253.         filespec += GLOBAL_CLOUD_TREE_FILE_NAME;
  254.  
  255.         if (FILE* f = fopen(filespec, "rb"))
  256.         {
  257.                 PrintMessage("Loading tree from %s", filespec.c_str());
  258.  
  259.                 int nDataSize = 0;
  260.                 fread(&nDataSize, 1, sizeof(nDataSize), f);
  261.  
  262.                 PodArray<int> arrData;
  263.                 arrData.CheckAllocated(nDataSize / 4);
  264.  
  265.                 int nLoadedItems = fread(arrData.GetElements(), 1, arrData.GetDataSize(), f);
  266.                 fclose(f);
  267.  
  268.                 int* pData = arrData.GetElements();
  269.  
  270.                 if (m_pSvoRoot)
  271.                 {
  272.                         if (Cry3DEngineBase::GetCVars()->e_svoTI_Active)
  273.                         {
  274.                                 m_pSvoRoot->AllocateSegment(CVoxelSegment::m_nNextCloudId++, 0, ecss_NotLoaded, ecss_NotLoaded, true);
  275.                                 nNodesCreated++;
  276.                         }
  277.                         else
  278.                         {
  279.                                 m_pSvoRoot->Load(pData, nNodesCreated, NULL, NULL);
  280.                         }
  281.                 }
  282.  
  283.                 if (pData - arrData.GetElements() == arrData.Count() || Cry3DEngineBase::GetCVars()->e_svoTI_Active)
  284.                 {
  285.                         PrintMessage("%d K bytes loaded", arrData.GetDataSize() / 1024);
  286.                         m_bReady = true;
  287.                 }
  288.                 else
  289.                         PrintMessage("Error loading %s", filespec.c_str());
  290.         }
  291. }
  292.  
  293. Vec3* GeneratePointsOnHalfSphere(int n);
  294. static Vec3* pKernelPoints = 0;
  295. const int nRaysNum = 512;
  296.  
  297. bool CSvoEnv::Render()
  298. {
  299.         FUNCTION_PROFILER_3DENGINE;
  300.  
  301.         AUTO_LOCK(m_csLockTree);
  302.  
  303.         CVoxelSegment::CheckAllocateTexturePool();
  304.  
  305.         CollectLights();
  306.  
  307.         CollectAnalyticalOccluders();
  308.  
  309.         //if(m_pDiffCM == (ITexture *)-1)
  310.         {
  311.                 m_pGlobalSpecCM = 0;
  312.                 m_fGlobalSpecCM_Mult = 0;
  313.  
  314.                 if (int nCount = gEnv->p3DEngine->GetObjectsByTypeInBox(eERType_Light, m_worldBox, (IRenderNode**)0))
  315.                 {
  316.                         PodArray<IRenderNode*> arrObjects(nCount, nCount);
  317.                         nCount = gEnv->p3DEngine->GetObjectsByTypeInBox(eERType_Light, m_worldBox, arrObjects.GetElements());
  318.  
  319.                         float fMaxRadius = 999;
  320.  
  321.                         for (int nL = 0; nL < nCount; nL++)
  322.                         {
  323.                                 ILightSource* pRN = (ILightSource*)arrObjects[nL];
  324.  
  325.                                 CDLight& rLight = pRN->GetLightProperties();
  326.  
  327.                                 if (rLight.m_fRadius > fMaxRadius && rLight.m_Flags & DLF_DEFERRED_CUBEMAPS)
  328.                                 {
  329.                                         fMaxRadius = rLight.m_fRadius;
  330.                                         m_pGlobalSpecCM = rLight.GetSpecularCubemap();
  331.                                         m_fGlobalSpecCM_Mult = rLight.m_SpecMult;
  332.                                 }
  333.                         }
  334.                 }
  335.         }
  336.  
  337.         // Teleport SVO root when camera comes close to the border of current SVO bounds
  338.         if (m_pSvoRoot && CVoxelSegment::m_nStreamingTasksInProgress == 0)
  339.                 ProcessSvoRootTeleport();
  340.  
  341.         static int nPrev_UpdateLighting = GetCVars()->e_svoTI_UpdateLighting;
  342.         if ((!nPrev_UpdateLighting || gEnv->IsEditing()) && GetCVars()->e_svoTI_UpdateLighting && GetCVars()->e_svoTI_IntegrationMode && m_bReady && m_pSvoRoot)
  343.                 DetectMovement_StatLights();
  344.         nPrev_UpdateLighting = GetCVars()->e_svoTI_UpdateLighting;
  345.  
  346.         static int nPrev_UpdateGeometry = GetCVars()->e_svoTI_UpdateGeometry;
  347.         if (!nPrev_UpdateGeometry && GetCVars()->e_svoTI_UpdateGeometry && m_bReady && m_pSvoRoot)
  348.         {
  349.                 DetectMovement_StaticGeom();
  350.                 CVoxelSegment::m_nVoxTrisCounter = 0;
  351.         }
  352.         nPrev_UpdateGeometry = GetCVars()->e_svoTI_UpdateGeometry;
  353.  
  354.         bool bMultiUserMode = false;
  355.         int nUserId = /*gSSRSystem ? gSSRSystem->GetCurRenderUserId(bMultiUserMode) : */ 0;
  356.  
  357.         if (IEntity* pEnt = GetSystem()->GetIEntitySystem()->FindEntityByName("MRI_Proxy"))
  358.         {
  359.                 gSvoEnv->m_matDvrTm = pEnt->GetWorldTM();
  360.  
  361.                 float fScale = 1.f / 32.f;
  362.                 Matrix44 mScale;
  363.                 mScale.SetIdentity();
  364.                 mScale.m00 = mScale.m11 = mScale.m22 = mScale.m33 = fScale;
  365.                 gSvoEnv->m_matDvrTm = gSvoEnv->m_matDvrTm * mScale;
  366.  
  367.                 Matrix44 mTrans;
  368.                 mTrans.SetIdentity();
  369.                 mTrans.SetTranslation(Vec3(-128 * fScale, -128 * fScale, -128 * fScale));
  370.  
  371.                 gSvoEnv->m_matDvrTm = gSvoEnv->m_matDvrTm * mTrans;
  372.         }
  373.         else
  374.         {
  375.                 gSvoEnv->m_matDvrTm.SetIdentity();
  376.         }
  377.  
  378.         CRenderObject* pObjVox = 0;
  379.         {
  380.                 pObjVox = Cry3DEngineBase::GetIdentityCRenderObject((*CVoxelSegment::m_pCurrPassInfo).ThreadID());
  381.                 pObjVox->m_II.m_AmbColor = Cry3DEngineBase::Get3DEngine()->GetSkyColor();
  382.                 pObjVox->m_II.m_Matrix.SetIdentity();
  383.                 pObjVox->m_nSort = 0;
  384.                 pObjVox->m_ObjFlags |= (/*FOB_NO_Z_PASS | */ FOB_NO_FOG);
  385.  
  386.                 SRenderObjData* pData = pObjVox->GetObjData();
  387.                 pData->m_fTempVars[0] = (float)nAtlasDimMaxXY;
  388.                 pData->m_fTempVars[1] = (float)nAtlasDimMaxXY;
  389.                 pData->m_fTempVars[2] = (float)nAtlasDimMaxZ;
  390.                 pData->m_fTempVars[3] = (float)(nVoxTexMaxDim / nVoxBloMaxDim);
  391.                 pData->m_fTempVars[4] = 0;//GetCVars()->e_svoDVR!=1 ? 0 : 11.111f;
  392.         }
  393.  
  394.         if (m_bReady && m_pSvoRoot)
  395.         {
  396.                 //              UpdatePVS();
  397.  
  398.                 static Vec3 arrLastCamPos[16];
  399.                 static Vec3 arrLastCamDir[16];
  400.                 static float arrLastUpdateTime[16];
  401.                 int nPoolId = max(0, nUserId);
  402.                 PodArray<SVF_P3F_C4B_T2F>& arrVertsOut = m_arrSvoProxyVertices;//arrVertsOutPool[nPoolId];
  403.  
  404.                 if (fabs(arrLastUpdateTime[nPoolId] - GetCurTimeSec()) > (/*bMultiUserMode ? 0.125f : 0.125f/64*/ 0.125f) || GetCVars()->e_svoEnabled >= 2 || (m_fStreamingStartTime >= 0) || (GetCVars()->e_svoDVR != 10))
  405.                 {
  406.                         arrLastUpdateTime[nPoolId] = GetCurTimeSec();
  407.                         arrLastCamPos[nPoolId] = CVoxelSegment::m_voxCam.GetPosition();
  408.                         arrLastCamDir[nPoolId] = CVoxelSegment::m_voxCam.GetViewdir();
  409.  
  410.                         CVoxelSegment::m_nPostponedCounter = CVoxelSegment::m_nCheckReadyCounter = CVoxelSegment::m_nAddPolygonToSceneCounter = 0;
  411.  
  412.                         arrVertsOut.Clear();
  413.  
  414.                         m_pSvoRoot->CheckReadyForRendering(0, m_arrForStreaming);
  415.  
  416.                         m_pSvoRoot->Render(0, 1, pObjVox, 0, arrVertsOut, m_arrForStreaming);
  417.  
  418.                         CheckUpdateMeshPools();
  419.                 }
  420.  
  421.                 // render DVR proxies
  422.                 /*if(arrVertsOut.Count() && GetCVars()->e_svoDVR == 10)
  423.                    {
  424.                    uint16 nDummyIndex = 0;
  425.  
  426.                    static SInputShaderResources res;
  427.                    static _smart_ptr< IMaterial > pMat = Cry3DEngineBase::MakeSystemMaterialFromShader("Total_Illumination.RenderDvrProxiesPass_GS", &res);
  428.                    pObjVox->m_pCurrMaterial = pMat;
  429.  
  430.                    Cry3DEngineBase::GetRenderer()->EF_AddPolygonToScene( pMat->GetShaderItem(),
  431.                     arrVertsOut.Count(), &arrVertsOut[0], NULL, pObjVox, (*CVoxelSegment::m_pCurrPassInfo), &nDummyIndex, 1, false );
  432.                    }*/
  433.         }
  434.  
  435.         int nMaxLoadedNodes = Cry3DEngineBase::GetCVars()->e_svoMaxBricksOnCPU;
  436.  
  437.         if (m_nVoxTexFormat != eTF_R8G8B8A8)
  438.                 nMaxLoadedNodes *= 4;
  439.  
  440.         //      if(GetCVars()->e_rsMode != RS_FAT_CLIENT)
  441.         {
  442.                 FRAME_PROFILER("CGlobalCloud::Render_StartStreaming", GetSystem(), PROFILE_3DENGINE);
  443.  
  444.                 for (int nTreeLevel = 0; (nTreeLevel < nVoxStreamQueueMaxSize); nTreeLevel++)
  445.                         for (int nDistId = 0; (nDistId < nVoxStreamQueueMaxSize); nDistId++)
  446.                         {
  447.                                 if (!m_bFirst_StartStreaming)
  448.                                         for (int i = 0; (i < m_arrForStreaming[nTreeLevel][nDistId].Count()) && (CVoxelSegment::m_nStreamingTasksInProgress < Cry3DEngineBase::GetCVars()->e_svoMaxStreamRequests); i++)
  449.                                         {
  450.                                                 if (CVoxelSegment::m_arrLoadedSegments.Count() > nMaxLoadedNodes)
  451.                                                         break;
  452.  
  453.                                                 if (/*m_arrForStreaming[nTreeLevel][nDistId][i]->m_nFileStreamSize>0 && */ !m_arrForStreaming[nTreeLevel][nDistId][i]->StartStreaming())
  454.                                                         break;
  455.                                         }
  456.  
  457.                                 m_arrForStreaming[nTreeLevel][nDistId].Clear();
  458.                         }
  459.  
  460.                 m_bFirst_StartStreaming = false;
  461.         }
  462.  
  463.         if (CVoxelSegment::m_arrLoadedSegments.Count() > (nMaxLoadedNodes - Cry3DEngineBase::GetCVars()->e_svoMaxStreamRequests))
  464.         {
  465.                 {
  466.                         FRAME_PROFILER("CGlobalCloud::Render_UnloadStreamable_Sort", GetSystem(), PROFILE_3DENGINE);
  467.  
  468.                         qsort(CVoxelSegment::m_arrLoadedSegments.GetElements(), CVoxelSegment::m_arrLoadedSegments.Count(), sizeof(CVoxelSegment::m_arrLoadedSegments[0]), CVoxelSegment::ComparemLastVisFrameID);
  469.                 }
  470.  
  471.                 {
  472.                         FRAME_PROFILER("CGlobalCloud::Render_UnloadStreamable_FreeRenderData", GetSystem(), PROFILE_3DENGINE);
  473.  
  474.                         int nNumNodesToDelete = 4 + Cry3DEngineBase::GetCVars()->e_svoMaxStreamRequests;//CVoxelSegment::m_arrLoadedSegments.Count()/1000;
  475.  
  476.                         int nNodesUnloaded = 0;
  477.                         while ((nNodesUnloaded < nNumNodesToDelete) &&
  478.                                (CVoxelSegment::m_arrLoadedSegments[nNodesUnloaded]->m_eStreamingStatus != ecss_InProgress) &&
  479.                                (CVoxelSegment::m_arrLoadedSegments[nNodesUnloaded]->m_nLastRendFrameId < (GetCurrPassMainFrameID() - 32)))
  480.                         {
  481.                                 CVoxelSegment::m_arrLoadedSegments[nNodesUnloaded]->FreeRenderData();
  482.                                 CVoxelSegment::m_arrLoadedSegments[nNodesUnloaded]->m_eStreamingStatus = ecss_NotLoaded;
  483.  
  484.                                 if (CSvoNode* pNode = CVoxelSegment::m_arrLoadedSegments[nNodesUnloaded]->m_pNode)
  485.                                 {
  486.                                         CSvoNode** ppChilds = CVoxelSegment::m_arrLoadedSegments[nNodesUnloaded]->m_pParentCloud->m_pNode->m_ppChilds;
  487.  
  488.                                         for (int nChildId = 0; nChildId < 8; nChildId++)
  489.                                         {
  490.                                                 if (ppChilds[nChildId] == pNode)
  491.                                                 {
  492.                                                         ppChilds[nChildId] = 0;
  493.                                                 }
  494.                                         }
  495.  
  496.                                         SAFE_DELETE(pNode);
  497.                                 }
  498.  
  499.                                 nNodesUnloaded++;
  500.                         }
  501.  
  502.                         CVoxelSegment::m_arrLoadedSegments.Delete(0, nNodesUnloaded);
  503.                 }
  504.         }
  505.  
  506.         CVoxelSegment::UpdateStreamingEngine();
  507.  
  508.         CVoxelSegment::m_nMaxBrickUpdates = max(1, bMultiUserMode ? Cry3DEngineBase::GetCVars()->e_svoMaxBrickUpdates * 16 : (Cry3DEngineBase::GetCVars()->e_svoMaxBrickUpdates / max(1, Cry3DEngineBase::GetCVars()->e_svoTI_LowSpecMode / (int)2 + 1)));
  509.         if (!(m_fStreamingStartTime < 0)) // if not bSvoReady yet
  510.                 CVoxelSegment::m_nMaxBrickUpdates *= 100;
  511.  
  512.         //if(nUserId == 0 || !bMultiUserMode)
  513.         {
  514.                 FRAME_PROFILER("CGlobalCloud::Render_BrickUpdate", GetSystem(), PROFILE_3DENGINE);
  515.  
  516.                 CVoxelSegment::m_nUpdatesInProgressTex = 0;
  517.                 CVoxelSegment::m_nUpdatesInProgressBri = 0;
  518.  
  519.                 for (int nTreeLevel = 0; (nTreeLevel < 16); nTreeLevel++)
  520.                 {
  521.                         for (int i = 0; (i < gSvoEnv->m_arrForBrickUpdate[nTreeLevel].Count()) && (CVoxelSegment::m_nUpdatesInProgressBri < CVoxelSegment::m_nMaxBrickUpdates); i++)
  522.                         {
  523.                                 CVoxelSegment* pSeg = gSvoEnv->m_arrForBrickUpdate[nTreeLevel][i];
  524.  
  525.                                 if (pSeg->m_eStreamingStatus == ecss_Ready)
  526.                                 {
  527.                                         CVoxelSegment::m_nUpdatesInProgressBri++;
  528.  
  529.                                         bool bWas = pSeg->CheckUpdateBrickRenderData(true);
  530.  
  531.                                         if (!pSeg->CheckUpdateBrickRenderData(false))
  532.                                         {
  533.                                                 break;
  534.                                         }
  535.  
  536.                                         if (!bWas)
  537.                                                 pSeg->PropagateDirtyFlag();
  538.                                 }
  539.                         }
  540.  
  541.                         gSvoEnv->m_arrForBrickUpdate[nTreeLevel].Clear();
  542.                 }
  543.  
  544.                 if (m_nTexNodePoolId)
  545.                 {
  546.                         FRAME_PROFILER("CGlobalCloud::Render_UpdateNodeRenderDataPtrs", GetSystem(), PROFILE_3DENGINE);
  547.  
  548.                         m_pSvoRoot->UpdateNodeRenderDataPtrs();
  549.                 }
  550.         }
  551.  
  552.         // render DVR quad
  553.         if (GetCVars()->e_svoDVR == 10)
  554.         {
  555.                 /*
  556.                    SVF_P3F_C4B_T2F arrVerts[4];
  557.                    ZeroStruct(arrVerts);
  558.                    uint16 arrIndices[] = { 0,2,1,2,3,1 };
  559.  
  560.                    for(int x=0; x<2; x++)
  561.                    {
  562.                    for(int y=0; y<2; y++)
  563.                    {
  564.                     int i = x*2+y;
  565.                     float X = (float)(GetRenderer()->GetWidth()*x);
  566.                     float Y = (float)(GetRenderer()->GetHeight()*y);
  567.                     GetRenderer()->UnProjectFromScreen(X, Y, 0.05f, &arrVerts[i].xyz.x, &arrVerts[i].xyz.y, &arrVerts[i].xyz.z);
  568.                     arrVerts[i].st.x = (float)x;
  569.                     arrVerts[i].st.y = (float)y;
  570.                    }
  571.                    }
  572.  
  573.                    static SInputShaderResources res;
  574.                    static _smart_ptr< IMaterial > pMat = Cry3DEngineBase::MakeSystemMaterialFromShader("Total_Illumination.BlendDvrIntoScene", &res);
  575.  
  576.                    int nRGBD=0, nNORM=0, nOPAC=0;
  577.                    GetRenderer()->GetISvoRenderer()->GetDynamicTextures(nRGBD, nNORM, nOPAC, NULL, NULL);
  578.                    pObjVox->m_nTextureID = nRGBD;
  579.  
  580.                    pObjVox->m_pCurrMaterial = pMat;
  581.  
  582.                    Cry3DEngineBase::GetRenderer()->EF_AddPolygonToScene( pMat->GetShaderItem(),
  583.                    4, &arrVerts[0], NULL, pObjVox, (*CVoxelSegment::m_pCurrPassInfo), &arrIndices[0], 6, false );
  584.                  */
  585.         }
  586.         else if (GetCVars()->e_svoDVR > 1)
  587.         {
  588.                 SVF_P3F_C4B_T2F arrVerts[4];
  589.                 ZeroStruct(arrVerts);
  590.                 uint16 arrIndices[] = { 0, 2, 1, 2, 3, 1 };
  591.  
  592.                 for (int x = 0; x < 2; x++)
  593.                 {
  594.                         for (int y = 0; y < 2; y++)
  595.                         {
  596.                                 int i = x * 2 + y;
  597.                                 float X = (float)(GetRenderer()->GetWidth() * x);
  598.                                 float Y = (float)(GetRenderer()->GetHeight() * y);
  599.                                 GetRenderer()->UnProjectFromScreen(X, Y, 0.05f, &arrVerts[i].xyz.x, &arrVerts[i].xyz.y, &arrVerts[i].xyz.z);
  600.                         }
  601.                 }
  602.  
  603.                 SInputShaderResourcesPtr pInputResource = GetRenderer()->EF_CreateInputShaderResource();
  604.                 SInputShaderResources& res = *pInputResource;
  605.  
  606.                 static _smart_ptr<IMaterial> pMat = Cry3DEngineBase::MakeSystemMaterialFromShader("Total_Illumination.SvoDebugDraw", &res);
  607.                 pObjVox->m_pCurrMaterial = pMat;
  608.  
  609.                 SRenderPolygonDescription poly(
  610.                   pObjVox,
  611.                   pMat->GetShaderItem(),
  612.                   4, &arrVerts[0], nullptr,
  613.                   &arrIndices[0], 6,
  614.                   EFSLIST_DECAL, false);
  615.  
  616.                 CVoxelSegment::m_pCurrPassInfo->GetIRenderView()->AddPolygon(poly, (*CVoxelSegment::m_pCurrPassInfo));
  617.  
  618.                 if (ICVar* pV = gEnv->pConsole->GetCVar("r_UseAlphaBlend"))
  619.                         pV->Set(1);
  620.         }
  621.  
  622.         if (Cry3DEngineBase::GetCVars()->e_svoDebug == 4 && 0)
  623.         {
  624.                 if (!pKernelPoints)
  625.                 {
  626.                         pKernelPoints = GeneratePointsOnHalfSphere(nRaysNum);
  627.                         //memcpy(pKernelPoints, &arrAO_Kernel[0], sizeof(Vec3)*32);
  628.  
  629.                         Cry3DEngineBase::PrintMessage("Organizing subsets . . .");
  630.  
  631.                         // try to organize point into 2 subsets, each subset should also present nice hemisphere
  632.                         for (int i = 0; i < 1000; i++)
  633.                         {
  634.                                 // find worst points in each of subsets and swap them
  635.                                 int m0 = GetWorstPointInSubSet(0, nRaysNum / 2);
  636.                                 int m1 = GetWorstPointInSubSet(nRaysNum / 2, nRaysNum);
  637.                                 std::swap(pKernelPoints[m0], pKernelPoints[m1]);
  638.                         }
  639.  
  640.                         Cry3DEngineBase::PrintMessage("Writing kernel.txt . . .");
  641.  
  642.                         FILE* f = 0;
  643.                         fopen_s(&f, "kernel.txt", "wt");
  644.                         if (f)
  645.                         {
  646.                                 //        fprintf(f, "#define nSampleNum %d\n", nRaysNum);
  647.                                 //        fprintf(f, "static float3 kernel[nSampleNum] = \n");
  648.                                 fprintf(f, "static float3 kernel_HS_%d[%d] = \n", nRaysNum, nRaysNum);
  649.                                 fprintf(f, "{\n");
  650.                                 for (int p = 0; p < nRaysNum; p++)
  651.                                         fprintf(f, "  float3( %.6f , %.6f, %.6f ),\n", pKernelPoints[p].x, pKernelPoints[p].y, pKernelPoints[p].z);
  652.                                 fprintf(f, "};\n");
  653.                                 fclose(f);
  654.                         }
  655.  
  656.                         Cry3DEngineBase::PrintMessage("Done");
  657.                 }
  658.  
  659.                 static Vec3 vPos = CVoxelSegment::m_voxCam.GetPosition();
  660.                 Cry3DEngineBase::DrawSphere(vPos, 4.f);
  661.                 for (int i = 0; i < nRaysNum; i++)
  662.                         Cry3DEngineBase::DrawSphere(vPos + pKernelPoints[i] * 4.f, .1f, (i < nRaysNum / 2) ? Col_Yellow : Col_Cyan);
  663.         }
  664.  
  665.         StartupStreamingTimeTest(CVoxelSegment::m_nStreamingTasksInProgress == 0 && CVoxelSegment::m_nUpdatesInProgressBri == 0 && CVoxelSegment::m_nUpdatesInProgressTex == 0 && CVoxelSegment::m_nTasksInProgressALL == 0);
  666.  
  667.         // show GI probe object in front of the camera
  668.         if (GetCVars()->e_svoDebug == 1)
  669.         {
  670.                 IEntity* pEnt = gEnv->pEntitySystem->FindEntityByName("svoti_debug_probe");
  671.                 if (pEnt)
  672.                 {
  673.                         CCamera& cam = CVoxelSegment::m_voxCam;
  674.                         CCamera camDef;
  675.                         pEnt->SetPos(cam.GetPosition() + cam.GetViewdir() * 1.f * camDef.GetFov() / cam.GetFov());
  676.                 }
  677.         }
  678.  
  679.         return true;
  680. }
  681.  
  682. void CSvoEnv::ProcessSvoRootTeleport()
  683. {
  684.         if (GetCVars()->e_svoDebug == 3 || GetCVars()->e_svoDebug == 6)
  685.                 Cry3DEngineBase::Get3DEngine()->DrawBBox(m_pSvoRoot->m_nodeBox, Col_Yellow);
  686.  
  687.         AABB rootBox = m_pSvoRoot->m_nodeBox;
  688.         Vec3 rootCenter = rootBox.GetCenter();
  689.         float fRootSize = rootBox.GetSize().x;
  690.         Vec3 vCamPos = gEnv->pSystem->GetViewCamera().GetPosition();
  691.  
  692.         for (int nA = 0; nA < 3; nA++)
  693.         {
  694.                 float fScrollDir = 0;
  695.                 float fThreshold = 2.f;
  696.  
  697.                 if (vCamPos[nA] > (rootBox.max[nA] - fRootSize / 4.f + fThreshold))
  698.                         fScrollDir = 1.f;
  699.                 else if (vCamPos[nA] < (rootBox.min[nA] + fRootSize / 4.f - fThreshold))
  700.                         fScrollDir = -1.f;
  701.  
  702.                 if (fScrollDir)
  703.                 {
  704.                         // scroll root node bounding box
  705.                         m_pSvoRoot->m_nodeBox.min[nA] += fRootSize / 2 * fScrollDir;
  706.                         m_pSvoRoot->m_nodeBox.max[nA] += fRootSize / 2 * fScrollDir;
  707.  
  708.                         if (m_pSvoRoot->m_pSeg)
  709.                         {
  710.                                 m_pSvoRoot->m_pSeg->m_nChildOffsetsDirty = 2;
  711.                                 m_pSvoRoot->m_pSeg->m_vSegOrigin[nA] = (m_pSvoRoot->m_nodeBox.max[nA] + m_pSvoRoot->m_nodeBox.min[nA]) / 2;
  712.                         }
  713.  
  714.                         // scroll pointers to childs, delete unnecessary childs
  715.                         if (m_pSvoRoot->m_ppChilds)
  716.                         {
  717.                                 for (int i = 0; i < 2; i++)
  718.                                 {
  719.                                         for (int j = 0; j < 2; j++)
  720.                                         {
  721.                                                 int nChildIdOld, nChildIdNew;
  722.  
  723.                                                 bool o = vCamPos[nA] > rootCenter[nA];
  724.                                                 bool n = !o;
  725.  
  726.                                                 if (nA == 0) // X
  727.                                                 {
  728.                                                         nChildIdOld = (o ? 4 : 0) | (i ? 2 : 0) | (j ? 1 : 0);
  729.                                                         nChildIdNew = (n ? 4 : 0) | (i ? 2 : 0) | (j ? 1 : 0);
  730.                                                 }
  731.                                                 else if (nA == 1) // Y
  732.                                                 {
  733.                                                         nChildIdOld = (i ? 4 : 0) | (o ? 2 : 0) | (j ? 1 : 0);
  734.                                                         nChildIdNew = (i ? 4 : 0) | (n ? 2 : 0) | (j ? 1 : 0);
  735.                                                 }
  736.                                                 else if (nA == 2) // Z
  737.                                                 {
  738.                                                         nChildIdOld = (j ? 4 : 0) | (i ? 2 : 0) | (o ? 1 : 0);
  739.                                                         nChildIdNew = (j ? 4 : 0) | (i ? 2 : 0) | (n ? 1 : 0);
  740.                                                 }
  741.  
  742.                                                 SAFE_DELETE(m_pSvoRoot->m_ppChilds[nChildIdNew]);
  743.                                                 m_pSvoRoot->m_ppChilds[nChildIdNew] = m_pSvoRoot->m_ppChilds[nChildIdOld];
  744.                                                 m_pSvoRoot->m_ppChilds[nChildIdOld] = NULL;
  745.                                         }
  746.                                 }
  747.                         }
  748.                 }
  749.         }
  750.  
  751.         gSvoEnv->m_vSvoOriginAndSize = Vec4(m_pSvoRoot->m_nodeBox.min, m_pSvoRoot->m_nodeBox.max.x - m_pSvoRoot->m_nodeBox.min.x);
  752. }
  753.  
  754. CSvoNode* CSvoNode::FindNodeByPosition(const Vec3& vPosWS, int nTreeLevelToFind, int nTreeLevelCur)
  755. {
  756.         if (nTreeLevelToFind == nTreeLevelCur)
  757.                 return this;
  758.  
  759.         Vec3 vNodeCenter = m_nodeBox.GetCenter();
  760.  
  761.         int nChildId =
  762.           ((vPosWS.x > vNodeCenter.x) ? 4 : 0) |
  763.           ((vPosWS.y > vNodeCenter.y) ? 2 : 0) |
  764.           ((vPosWS.z > vNodeCenter.z) ? 1 : 0);
  765.  
  766.         if (m_ppChilds && m_ppChilds[nChildId])
  767.                 return m_ppChilds[nChildId]->FindNodeByPosition(vPosWS, nTreeLevelToFind, nTreeLevelCur + 1);
  768.  
  769.         return NULL;
  770. }
  771.  
  772. void CSvoNode::OnStatLightsChanged(const AABB& objBox)
  773. {
  774.         if (Overlap::AABB_AABB(objBox, m_nodeBox))
  775.         {
  776.                 m_pSeg->m_bStatLightsChanged = 1;
  777.  
  778.                 if (m_ppChilds)
  779.                 {
  780.                         for (int nChildId = 0; nChildId < 8; nChildId++)
  781.                         {
  782.                                 if (m_ppChilds[nChildId])
  783.                                 {
  784.                                         m_ppChilds[nChildId]->OnStatLightsChanged(objBox);
  785.                                 }
  786.                         }
  787.                 }
  788.         }
  789. }
  790.  
  791. AABB CSvoNode::GetChildBBox(int nChildId)
  792. {
  793.         int x = (nChildId / 4);
  794.         int y = (nChildId - x * 4) / 2;
  795.         int z = (nChildId - x * 4 - y * 2);
  796.         Vec3 vSize = m_nodeBox.GetSize() * 0.5f;
  797.         Vec3 vOffset = vSize;
  798.         vOffset.x *= x;
  799.         vOffset.y *= y;
  800.         vOffset.z *= z;
  801.         AABB childBox;
  802.         childBox.min = m_nodeBox.min + vOffset;
  803.         childBox.max = childBox.min + vSize;
  804.         return childBox;
  805. }
  806.  
  807. bool CSvoNode::CheckReadyForRendering(int nTreeLevel, PodArray<CVoxelSegment*> arrForStreaming[nVoxStreamQueueMaxSize][nVoxStreamQueueMaxSize])
  808. {
  809.         bool bAllReady = true;
  810.  
  811.         if (m_pSeg)
  812.         {
  813.                 CVoxelSegment* pCloud = m_pSeg;
  814.  
  815.                 //              if(CVoxelSegment::voxCamera.IsAABBVisible_E(m_nodeBox))
  816.                 if (GetCurrPassMainFrameID() > 1)
  817.                         pCloud->m_nLastRendFrameId = max(pCloud->m_nLastRendFrameId, GetCurrPassMainFrameID() - 1);
  818.  
  819.                 CVoxelSegment::m_nCheckReadyCounter++;
  820.  
  821.                 if (pCloud->m_eStreamingStatus == ecss_NotLoaded)
  822.                 {
  823.                         float fBoxSize = m_nodeBox.GetSize().x;
  824.  
  825.                         int nDistId = min(nVoxStreamQueueMaxSize - 1, (int)(m_nodeBox.GetDistance(CVoxelSegment::m_voxCam.GetPosition()) / fBoxSize));
  826.                         int nTLevId = min(nVoxStreamQueueMaxSize - 1, nTreeLevel);
  827.                         if (arrForStreaming[nTLevId][nDistId].Count() < Cry3DEngineBase::GetCVars()->e_svoMaxStreamRequests)
  828.                                 arrForStreaming[nTLevId][nDistId].Add(pCloud);
  829.                 }
  830.  
  831.                 if (pCloud->m_eStreamingStatus != ecss_Ready)
  832.                 {
  833.                         bAllReady = false;
  834.                 }
  835.  
  836.                 if (pCloud->m_eStreamingStatus == ecss_Ready)
  837.                 {
  838.                         if (!pCloud->CheckUpdateBrickRenderData(true))
  839.                         {
  840.                                 if (gSvoEnv->m_arrForBrickUpdate[nTreeLevel].Count() < CVoxelSegment::m_nMaxBrickUpdates)
  841.                                         gSvoEnv->m_arrForBrickUpdate[nTreeLevel].Add(pCloud);
  842.                                 bAllReady = false;
  843.                         }
  844.                 }
  845.         }
  846.  
  847.         return bAllReady;
  848. }
  849.  
  850. CSvoNode* CSvoNode::FindNodeByPoolAffset(int nAllocatedAtlasOffset)
  851. {
  852.         if (nAllocatedAtlasOffset == m_pSeg->m_nAllocatedAtlasOffset)
  853.                 return this;
  854.  
  855.         if (m_ppChilds)
  856.         {
  857.                 for (int nChildId = 0; nChildId < 8; nChildId++)
  858.                 {
  859.                         if (m_ppChilds[nChildId])
  860.                         {
  861.                                 if (CSvoNode* pRes = m_ppChilds[nChildId]->FindNodeByPoolAffset(nAllocatedAtlasOffset))
  862.                                         return pRes;
  863.                         }
  864.                 }
  865.         }
  866.  
  867.         return 0;
  868. }
  869.  
  870. void CSvoNode::RegisterMovement(const AABB& objBox)
  871. {
  872.         if (Overlap::AABB_AABB(objBox, m_nodeBox))
  873.         {
  874.                 //              m_nRequestBrickUpdateFrametId = GetCurrPassMainFrameID();
  875.  
  876.                 //m_bLightingChangeDetected = true;
  877.  
  878.                 if (m_pSeg &&
  879.                     m_pSeg->m_eStreamingStatus != ecss_NotLoaded &&
  880.                     m_pSeg->GetBoxSize() <= Cry3DEngineBase::GetCVars()->e_svoMaxNodeSize)
  881.                 {
  882.                         //                      m_pCloud->m_bRefreshRequeste d = true;
  883.                 }
  884.  
  885.                 if (m_ppChilds)
  886.                 {
  887.                         for (int nChildId = 0; nChildId < 8; nChildId++)
  888.                         {
  889.                                 if (m_ppChilds[nChildId])
  890.                                 {
  891.                                         m_ppChilds[nChildId]->RegisterMovement(objBox);
  892.                                 }
  893.                         }
  894.                 }
  895.         }
  896. }
  897.  
  898. Vec3i ComputeDataCoord(int nAtlasOffset)
  899. {
  900.         static const Vec3i vAtlasDimInt(32, 32, 32);
  901.  
  902.         //      nAtlasOffset = clamp(nAtlasOffset, 0, vAtlasDimInt*vAtlasDimInt*vAtlasDimInt);
  903.  
  904.         Vec3i vOffset3D;
  905.         vOffset3D.z = nAtlasOffset / vAtlasDimInt.x / vAtlasDimInt.y;
  906.         vOffset3D.y = (nAtlasOffset / vAtlasDimInt.x - vOffset3D.z * vAtlasDimInt.y);
  907.         vOffset3D.x = nAtlasOffset - vOffset3D.z * vAtlasDimInt.y * vAtlasDimInt.y - vOffset3D.y * vAtlasDimInt.x;
  908.  
  909.         return vOffset3D;
  910. }
  911.  
  912. void CSvoNode::Render(PodArray<struct SPvsItem>* pSortedPVS, uint64 nNodeKey, CRenderObject* pObj, int nTreeLevel, PodArray<SVF_P3F_C4B_T2F>& arrVertsOut, PodArray<CVoxelSegment*> arrForStreaming[nVoxStreamQueueMaxSize][nVoxStreamQueueMaxSize])
  913. {
  914.         float fBoxSize = m_nodeBox.GetSize().x;
  915.  
  916.         Vec3 vCamPos = CVoxelSegment::m_voxCam.GetPosition();
  917.  
  918.         const float fNodeToCamDist = m_nodeBox.GetDistance(vCamPos);
  919.  
  920.         const float fBoxSizeRated = fBoxSize * Cry3DEngineBase::GetCVars()->e_svoTI_VoxelizaionLODRatio;
  921.  
  922.         bool bDrawThisNode = false;
  923.  
  924.         if (m_ppChilds)
  925.         {
  926.                 for (int nChildId = 0; nChildId < 8; nChildId++)
  927.                 {
  928.                         if (m_ppChilds[nChildId] && m_ppChilds[nChildId]->m_bForceRecreate && !m_ppChilds[nChildId]->IsStreamingInProgress())
  929.                         {
  930.                                 SAFE_DELETE(m_ppChilds[nChildId]);
  931.                                 gSvoEnv->m_fSvoFreezeTime = gEnv->pTimer->GetAsyncCurTime();
  932.                                 ZeroStruct(gSvoEnv->m_arrVoxelizeMeshesCounter);
  933.                         }
  934.                 }
  935.         }
  936.  
  937.         // auto allocate new childs
  938.         if (Cry3DEngineBase::GetCVars()->e_svoTI_Active && m_pSeg && m_pSeg->m_eStreamingStatus == ecss_Ready && m_pSeg->m_pBlockInfo)
  939.                 if (m_pSeg->m_dwChildTrisTest || (m_pSeg->GetBoxSize() > Cry3DEngineBase::GetCVars()->e_svoMaxNodeSize) || (Cry3DEngineBase::GetCVars()->e_svoTI_Troposphere_Subdivide))
  940.                 {
  941.                         if (fNodeToCamDist < fBoxSizeRated && !bDrawThisNode)
  942.                         {
  943.                                 CheckAllocateChilds();
  944.                         }
  945.                 }
  946.  
  947.         if ((!m_ppChilds || (fNodeToCamDist > fBoxSizeRated) || (fBoxSize <= Cry3DEngineBase::GetCVars()->e_svoMinNodeSize))
  948.             || (!CVoxelSegment::m_voxCam.IsAABBVisible_E(m_nodeBox) && (fNodeToCamDist * 1.5 > fBoxSizeRated)))
  949.         {
  950.                 bDrawThisNode = true;
  951.         }
  952.  
  953.         nTreeLevel++;
  954.  
  955.         if (!bDrawThisNode && m_ppChilds)
  956.         {
  957.                 if (Cry3DEngineBase::GetCVars()->e_svoDVR)
  958.                 {
  959.                         // check one child per frame
  960.                         int nChildId = GetCurrPassMainFrameID() % 8;
  961.  
  962.                         {
  963.                                 CSvoNode* pChild = m_ppChilds[nChildId];
  964.                                 if (pChild && pChild->m_pSeg)
  965.                                         if (!pChild->CheckReadyForRendering(nTreeLevel, arrForStreaming))
  966.                                                 //                                      if(CVoxelSegment::voxCamera.IsAABBVisible_E(pChild->m_nodeBox))
  967.                                                 bDrawThisNode = true;
  968.                         }
  969.                 }
  970.                 else
  971.                 {
  972.                         for (int nChildId = 0; nChildId < 8; nChildId++)
  973.                         {
  974.                                 CSvoNode* pChild = m_ppChilds[nChildId];
  975.                                 if (pChild && pChild->m_pSeg)
  976.                                         if (!pChild->CheckReadyForRendering(nTreeLevel, arrForStreaming))
  977.                                                 //                                      if(CVoxelSegment::voxCamera.IsAABBVisible_E(pChild->m_nodeBox))
  978.                                                 bDrawThisNode = true;
  979.                         }
  980.                 }
  981.         }
  982.  
  983.         if (bDrawThisNode)
  984.         {
  985.                 if (m_pSeg)
  986.                 {
  987.                         //                      if(m_pCloud->m_voxVolumeBox.IsReset() || CVoxelSegment::voxCamera.IsAABBVisible_E(m_pCloud->m_voxVolumeBox))
  988.                         {
  989.                                 if (CVoxelSegment::m_voxCam.IsAABBVisible_E(m_nodeBox))
  990.                                         m_pSeg->RenderMesh(pObj, arrVertsOut);
  991.                         }
  992.                 }
  993.  
  994.                 if (m_pSeg && Cry3DEngineBase::GetCVars()->e_svoDebug == 2)
  995.                         if (CVoxelSegment::m_voxCam.IsAABBVisible_E(m_nodeBox) && m_nodeBox.GetSize().z <= Cry3DEngineBase::GetCVars()->e_svoMaxNodeSize)
  996.                         {
  997.                                 //        if(fBoxSize <= Cry3DEngineBase::GetCVars()->e_svoMinNodeSize)
  998.                                 //          Cry3DEngineBase::Get3DEngine()->DrawBBox(m_nodeBox);
  999.  
  1000.                                 Cry3DEngineBase::Get3DEngine()->DrawBBox(m_nodeBox,
  1001.                                                                          ColorF(
  1002.                                                                            (m_nodeBox.GetSize().z == Cry3DEngineBase::GetCVars()->e_svoMinNodeSize),
  1003.                                                                            ((m_nodeBox.GetSize().z - Cry3DEngineBase::GetCVars()->e_svoMinNodeSize) / (Cry3DEngineBase::GetCVars()->e_svoMaxNodeSize - Cry3DEngineBase::GetCVars()->e_svoMinNodeSize)),
  1004.                                                                            (m_nodeBox.GetSize().z == Cry3DEngineBase::GetCVars()->e_svoMaxNodeSize),
  1005.                                                                            1));
  1006.                         }
  1007.         }
  1008.         else if (m_ppChilds)
  1009.         {
  1010.                 Vec3 vSrcCenter = m_nodeBox.GetCenter();
  1011.  
  1012.                 int nFirst =
  1013.                   ((vCamPos.x > vSrcCenter.x) ? 4 : 0) |
  1014.                   ((vCamPos.y > vSrcCenter.y) ? 2 : 0) |
  1015.                   ((vCamPos.z > vSrcCenter.z) ? 1 : 0);
  1016.  
  1017.                 byte childId[8];
  1018.                 childId[0] = nFirst;
  1019.                 childId[1] = nFirst ^ 1;
  1020.                 childId[2] = nFirst ^ 2;
  1021.                 childId[3] = nFirst ^ 4;
  1022.                 childId[4] = nFirst ^ 3;
  1023.                 childId[5] = nFirst ^ 5;
  1024.                 childId[6] = nFirst ^ 6;
  1025.                 childId[7] = nFirst ^ 7;
  1026.  
  1027.                 for (int c = 0; c < 8; c++)
  1028.                 {
  1029.                         int nChildId = childId[c];
  1030.                         CSvoNode* pChild = m_ppChilds[nChildId];
  1031.                         if (pChild)
  1032.                                 pChild->Render(NULL, (nNodeKey << 3) + (nChildId), pObj, nTreeLevel, arrVertsOut, arrForStreaming);
  1033.                 }
  1034.         }
  1035. }
  1036.  
  1037. void CSvoNode::CollectResetVisNodes(PvsMap& arrNodes, uint64 nNodeKey)
  1038. {
  1039.         //  if(m_nVisId)
  1040.         //  {
  1041.         //    if(m_ppChilds)
  1042.         //    {
  1043.         //      std::pair<byte,byte> childVisMask;
  1044.         //      childVisMask.first = childVisMask.second = 0;
  1045.         //
  1046.         //      for(int nChildId=0; nChildId<8; nChildId++)
  1047.         //      {
  1048.         //        if(m_ppChilds[nChildId])
  1049.         //        {
  1050.         //          childVisMask.first |= (1<<nChildId); // mark this info bit as valid
  1051.         //          if(m_ppChilds[nChildId]->m_nVisId)
  1052.         //            childVisMask.second |= (1<<nChildId);  // store vis flag
  1053.         //
  1054.         //          m_ppChilds[nChildId]->CollectResetVisNodes(arrNodes, (nNodeKey<<3) + nChildId);
  1055.         //        }
  1056.         //      }
  1057.         //
  1058.         //      arrNodes[nNodeKey] = childVisMask;
  1059.         //    }
  1060.         //
  1061.         //    m_nVisId = 0;
  1062.         //  }
  1063. }
  1064.  
  1065. Vec3* GeneratePointsOnHalfSphere(int n)
  1066. {
  1067.         ((C3DEngine*)gEnv->p3DEngine)->PrintMessage("Generating kernel of %d points . . .", n);
  1068.  
  1069.         int i, j;
  1070.         int counter = 0, countmax = n * 1024 * 4;
  1071.         int minp1 = 0, minp2 = 0;
  1072.         float d = 0, mind = 0;
  1073.         static Vec3 p[1000];
  1074.         Vec3 p1(0, 0, 0), p2(0, 0, 0);
  1075.  
  1076.         // Create the initial random set of points
  1077.  
  1078.         srand(0);
  1079.  
  1080.         float fMinZ = 0.5f;
  1081.  
  1082.         for (i = 0; i < n; i++)
  1083.         {
  1084.                 p[i].x = float(cry_random(-500, 500));
  1085.                 p[i].y = float(cry_random(-500, 500));
  1086.                 p[i].z = fabs(float(cry_random(-500, 500)));
  1087.  
  1088.                 if (p[i].GetLength() < 100)
  1089.                 {
  1090.                         i--;
  1091.                         continue;
  1092.                 }
  1093.  
  1094.                 p[i].Normalize();
  1095.  
  1096.                 p[i].z += fMinZ;
  1097.  
  1098.                 p[i].Normalize();
  1099.         }
  1100.  
  1101.         while (counter < countmax)
  1102.         {
  1103.                 if (counter && (counter % 10000) == 0)
  1104.                         ((C3DEngine*)gEnv->p3DEngine)->PrintMessage("Adjusting points, pass %d K of %d K . . .", counter / 1000, countmax / 1000);
  1105.  
  1106.                 // Find the closest two points
  1107.  
  1108.                 minp1 = 0;
  1109.                 minp2 = 1;
  1110.                 mind = sqrt(p[minp1].GetSquaredDistance2D(p[minp2]));
  1111.  
  1112.                 for (i = 0; i < n - 1; i++)
  1113.                 {
  1114.                         for (j = i + 1; j < n; j++)
  1115.                         {
  1116.                                 if ((d = sqrt(p[i].GetSquaredDistance2D(p[j]))) < mind)
  1117.                                 {
  1118.                                         mind = d;
  1119.                                         minp1 = i;
  1120.                                         minp2 = j;
  1121.                                 }
  1122.                         }
  1123.                 }
  1124.  
  1125.                 // Move the two minimal points apart, in this case by 1%, but should really vary this for refinement
  1126.  
  1127.                 if (d == 0)
  1128.                         p[minp2].z += 0.001f;
  1129.  
  1130.                 p1 = p[minp1];
  1131.                 p2 = p[minp2];
  1132.  
  1133.                 p[minp2].x = p1.x + 1.01f * (p2.x - p1.x);
  1134.                 p[minp2].y = p1.y + 1.01f * (p2.y - p1.y);
  1135.                 p[minp2].z = p1.z + 1.01f * (p2.z - p1.z);
  1136.  
  1137.                 p[minp1].x = p1.x - 0.01f * (p2.x - p1.x);
  1138.                 p[minp1].y = p1.y - 0.01f * (p2.y - p1.y);
  1139.                 p[minp1].z = p1.z - 0.01f * (p2.z - p1.z);
  1140.  
  1141.                 p[minp2].z = max(p[minp2].z, fMinZ);
  1142.                 p[minp1].z = max(p[minp1].z, fMinZ);
  1143.  
  1144.                 p[minp1].Normalize();
  1145.                 p[minp2].Normalize();
  1146.  
  1147.                 counter++;
  1148.         }
  1149.  
  1150.         ((C3DEngine*)gEnv->p3DEngine)->PrintMessage("  Finished generating kernel");
  1151.  
  1152.         return p;
  1153. }
  1154.  
  1155. CSvoEnv::CSvoEnv(const AABB& worldBox)
  1156. {
  1157.         gSvoEnv = this;
  1158.  
  1159.         m_vSvoOriginAndSize = Vec4(worldBox.min, worldBox.max.x - worldBox.min.x);
  1160.         m_nDebugDrawVoxelsCounter = 0;
  1161.         m_nVoxTexFormat = eTF_R8G8B8A8; // eTF_BC3
  1162.  
  1163.         #ifdef FEATURE_SVO_GI_ALLOW_HQ
  1164.                 #ifdef FEATURE_SVO_GI_USE_MESH_RT
  1165.         m_nTexTrisPoolId = 0;
  1166.                 #endif
  1167.         m_nTexRgb0PoolId = 0;
  1168.         m_nTexRgb1PoolId = 0;
  1169.         m_nTexDynlPoolId = 0;
  1170.         m_nTexRgb2PoolId = 0;
  1171.         m_nTexRgb3PoolId = 0;
  1172.         m_nTexRgb4PoolId = 0;
  1173.         m_nTexNormPoolId = 0;
  1174.         m_nTexAldiPoolId = 0;
  1175.         #endif
  1176.         m_nTexOpasPoolId = 0;
  1177.         m_nTexNodePoolId = 0;
  1178.  
  1179.         m_prevCheckVal = -1000000;
  1180.         m_matDvrTm = Matrix44(Matrix34::CreateIdentity());
  1181.         m_fStreamingStartTime = 0;
  1182.         m_nNodeCounter = 0;
  1183.         m_nDynNodeCounter_DYNL = m_nDynNodeCounter = 0;
  1184.  
  1185.         if (GetCVars()->e_svoTI_Active)
  1186.                 GetCVars()->e_svoVoxelPoolResolution = min((int)256, GetCVars()->e_svoVoxelPoolResolution);
  1187.  
  1188.         CVoxelSegment::nVoxTexPoolDimXY = min(GetCVars()->e_svoVoxelPoolResolution, (int)512);
  1189.         CVoxelSegment::nVoxTexPoolDimZ = min(GetCVars()->e_svoVoxelPoolResolution, (int)1024);
  1190.         CVoxelSegment::nVoxTexPoolDimZ = max(CVoxelSegment::nVoxTexPoolDimZ, (int)256);
  1191.  
  1192.         m_worldBox = worldBox;
  1193.         m_bReady = false;
  1194.         m_pSvoRoot = new CSvoNode(AABB(Vec3(0, 0, 0), Vec3((float)GetCVars()->e_svoRootSize)), NULL);
  1195.         m_pGlobalSpecCM = (ITexture*)0;
  1196.         m_fGlobalSpecCM_Mult = 1;
  1197.         m_fSvoFreezeTime = -1;
  1198.         ZeroStruct(gSvoEnv->m_arrVoxelizeMeshesCounter);
  1199.         GetRenderer()->GetISvoRenderer(); // allocate SVO sub-system in renderer
  1200.         m_bFirst_SvoFreezeTime = m_bFirst_StartStreaming = true;
  1201.         m_bStreamingDonePrev = false;
  1202. }
  1203.  
  1204. CSvoEnv::~CSvoEnv()
  1205. {
  1206.         // wait until all streaming requests are complete
  1207.         while (CVoxelSegment::m_nStreamingTasksInProgress)
  1208.         {
  1209.                 CrySleep(20);
  1210.                 CVoxelSegment::UpdateStreamingEngine();
  1211.         }
  1212.  
  1213.         SAFE_DELETE(m_pSvoRoot);
  1214.  
  1215.         #ifdef FEATURE_SVO_GI_ALLOW_HQ
  1216.                 #ifdef FEATURE_SVO_GI_USE_MESH_RT
  1217.         GetRenderer()->RemoveTexture(m_nTexTrisPoolId);
  1218.                 #endif
  1219.         GetRenderer()->RemoveTexture(m_nTexRgb0PoolId);
  1220.         GetRenderer()->RemoveTexture(m_nTexRgb1PoolId);
  1221.         GetRenderer()->RemoveTexture(m_nTexDynlPoolId);
  1222.         GetRenderer()->RemoveTexture(m_nTexRgb2PoolId);
  1223.         GetRenderer()->RemoveTexture(m_nTexRgb3PoolId);
  1224.         GetRenderer()->RemoveTexture(m_nTexRgb4PoolId);
  1225.         GetRenderer()->RemoveTexture(m_nTexNormPoolId);
  1226.         GetRenderer()->RemoveTexture(m_nTexAldiPoolId);
  1227.         #endif
  1228.         GetRenderer()->RemoveTexture(m_nTexOpasPoolId);
  1229.         GetRenderer()->RemoveTexture(m_nTexNodePoolId);
  1230.  
  1231.         GetCVars()->e_svoTI_Active = 0;
  1232.         GetCVars()->e_svoTI_Apply = 0;
  1233.         GetCVars()->e_svoLoadTree = 0;
  1234.         GetCVars()->e_svoEnabled = 0;
  1235.         gSvoEnv = NULL;
  1236.         GetRenderer()->GetISvoRenderer()->Release();
  1237.  
  1238.         {
  1239.                 AUTO_MODIFYLOCK(CVoxelSegment::m_arrLockedTextures.m_Lock);
  1240.                 for (int i = 0; i < CVoxelSegment::m_arrLockedTextures.Count(); i++)
  1241.                         CVoxelSegment::m_arrLockedTextures[i]->Release();
  1242.                 CVoxelSegment::m_arrLockedTextures.Reset();
  1243.         }
  1244.  
  1245.         {
  1246.                 AUTO_MODIFYLOCK(CVoxelSegment::m_arrLockedMaterials.m_Lock);
  1247.                 for (int i = 0; i < CVoxelSegment::m_arrLockedMaterials.Count(); i++)
  1248.                         CVoxelSegment::m_arrLockedMaterials[i]->Release();
  1249.                 CVoxelSegment::m_arrLockedMaterials.Reset();
  1250.         }
  1251. }
  1252.  
  1253. void CSvoNode::CheckAllocateSegment(int nLod)
  1254. {
  1255.         if (!m_pSeg)
  1256.         {
  1257.                 int nCloudId = CVoxelSegment::m_nNextCloudId;
  1258.                 CVoxelSegment::m_nNextCloudId++;
  1259.  
  1260.                 AllocateSegment(nCloudId, -1, nLod, ecss_Ready, false);
  1261.         }
  1262. }
  1263.  
  1264. CSvoNode::CSvoNode(const AABB& box, CSvoNode* pParent)
  1265. {
  1266.         ZeroStruct(*this);
  1267.  
  1268.         m_pParent = pParent;
  1269.         m_nodeBox = box;
  1270.  
  1271.         if (!pParent)
  1272.                 gSvoEnv->m_vSvoOriginAndSize = Vec4(box.min, box.max.x- box.min.x);
  1273.  
  1274.         gSvoEnv->m_nNodeCounter++;
  1275. }
  1276.  
  1277. CSvoNode::~CSvoNode()
  1278. {
  1279.         DeleteChilds();
  1280.  
  1281.         if (m_pSeg)
  1282.         {
  1283.                 CVoxelSegment* pCloud = m_pSeg;
  1284.                 delete pCloud;
  1285.         }
  1286.         m_pSeg = 0;
  1287.  
  1288.         gSvoEnv->m_nNodeCounter--;
  1289. }
  1290.  
  1291. void CSvoNode::Load(int*& pData, int& nNodesCreated, CSvoNode* pParent, AABB* pAreaBox)
  1292. {
  1293.         m_pParent = pParent;
  1294.  
  1295.         int nChildsMask = *pData;
  1296.         pData++;
  1297.  
  1298.         if (nChildsMask)
  1299.         {
  1300.                 if (!m_ppChilds)
  1301.                 {
  1302.                         m_ppChilds = new CSvoNode*[8];
  1303.                         memset(m_ppChilds, 0, sizeof(m_ppChilds[0]) * 8);
  1304.                 }
  1305.         }
  1306.  
  1307.         for (int nChildId = 0; nChildId < 8; nChildId++)
  1308.         {
  1309.                 if (nChildsMask & (1 << nChildId))
  1310.                 {
  1311.                         if (!m_ppChilds[nChildId])
  1312.                                 m_ppChilds[nChildId] = new CSvoNode(GetChildBBox(nChildId), this);
  1313.                         nNodesCreated++;
  1314.                 }
  1315.                 else if (m_ppChilds && m_ppChilds[nChildId])
  1316.                 {
  1317.                         SAFE_DELETE(m_ppChilds[nChildId]);
  1318.                 }
  1319.         }
  1320.  
  1321.         int nCloudsNum = *pData;
  1322.         pData++;
  1323.  
  1324.         if (nCloudsNum)
  1325.         {
  1326.                 int nCloudId = *pData;
  1327.                 pData++;
  1328.                 if (!m_pSeg)
  1329.                         AllocateSegment(nCloudId, 0, ecss_NotLoaded, ecss_NotLoaded, true);
  1330.                 m_pSeg->m_nFileStreamOffset64 = *(int64*)pData;
  1331.                 pData++;
  1332.                 pData++;
  1333.                 m_pSeg->m_nFileStreamSize = *pData;
  1334.                 pData++;
  1335.         }
  1336.         else
  1337.         {
  1338.                 SAFE_DELETE(m_pSeg);
  1339.         }
  1340.  
  1341.         if (pAreaBox && !Overlap::AABB_AABB(*pAreaBox, m_nodeBox))
  1342.                 return;
  1343.  
  1344.         for (int nChildId = 0; nChildId < 8; nChildId++)
  1345.         {
  1346.                 if (m_ppChilds && m_ppChilds[nChildId])
  1347.                         m_ppChilds[nChildId]->Load(pData, nNodesCreated, this, pAreaBox);
  1348.         }
  1349. }
  1350.  
  1351. CVoxelSegment* CSvoNode::AllocateSegment(int nCloudId, int nStationId, int nLod, EFileStreamingStatus eStreamingStatus, bool bDroppedOnDisk)
  1352. {
  1353.         CVoxelSegment* pCloud = new CVoxelSegment(this, true, eStreamingStatus, bDroppedOnDisk);
  1354.  
  1355.         AABB cloudBox = m_nodeBox;
  1356.         Vec3 vCenter = m_nodeBox.GetCenter();
  1357.         cloudBox.min -= vCenter;
  1358.         cloudBox.max -= vCenter;
  1359.         pCloud->SetBoxOS(cloudBox);
  1360.         //      pCloud->SetRenderBBox(m_nodeBox);
  1361.  
  1362.         pCloud->SetID(nCloudId);
  1363.         //pCloud->m_nStationId = nStationId;
  1364.         pCloud->m_vSegOrigin = vCenter;
  1365.  
  1366.         m_pSeg = pCloud;
  1367.  
  1368.         if (m_pParent)
  1369.                 m_pSeg->m_pParentCloud = m_pParent->m_pSeg;
  1370.  
  1371.         pCloud->m_vStaticGeomCheckSumm = GetStatGeomCheckSumm();
  1372.  
  1373.         return pCloud;
  1374. }
  1375.  
  1376. Vec3i CSvoNode::GetStatGeomCheckSumm()
  1377. {
  1378.         Vec3i vCheckSumm(0, 0, 0);
  1379.  
  1380.         float fNodeSize = m_nodeBox.GetSize().x;
  1381.  
  1382.         if (fNodeSize > Cry3DEngineBase::GetCVars()->e_svoMaxNodeSize)
  1383.                 return vCheckSumm;
  1384.  
  1385.         PodArray<IRenderNode*> lstObjects;
  1386.         AABB boxEx = m_nodeBox;
  1387.         float fBorder = fNodeSize / nVoxTexMaxDim;
  1388.         boxEx.Expand(Vec3(fBorder, fBorder, fBorder));
  1389.         Cry3DEngineBase::Get3DEngine()->GetObjectsByTypeGlobal(lstObjects, eERType_Brush, &boxEx);
  1390.         Cry3DEngineBase::Get3DEngine()->GetVisAreaManager()->GetObjectsByType(lstObjects, eERType_Brush, &boxEx);
  1391.  
  1392.         float fPrecisioin = 1000;
  1393.  
  1394.         for (int i = 0; i < lstObjects.Count(); i++)
  1395.         {
  1396.                 IRenderNode* pNode = lstObjects[i];
  1397.  
  1398.                 if (pNode->GetRndFlags() & (ERF_HIDDEN | ERF_COLLISION_PROXY | ERF_RAYCAST_PROXY))
  1399.                         continue;
  1400.  
  1401.                 //                              if(!(pNode->GetRndFlags() & (ERF_CASTSHADOWMAPS|ERF_CASTSHADOWINTORAMMAP)))
  1402.                 //                              continue;
  1403.  
  1404.                 AABB box = pNode->GetBBox();
  1405.  
  1406.                 IStatObj* pStatObj = pNode->GetEntityStatObj();
  1407.  
  1408.                 if (pStatObj && pStatObj->m_eStreamingStatus == ecss_Ready)
  1409.                 {
  1410.                         vCheckSumm += Vec3i(box.min * fPrecisioin);
  1411.                         vCheckSumm += Vec3i(box.max * fPrecisioin * 2);
  1412.                         vCheckSumm.x += uint16(((uint64)pNode->GetMaterial()) / 64);
  1413.                 }
  1414.         }
  1415.  
  1416.         // add visarea shapes
  1417.         for (int v = 0;; v++)
  1418.         {
  1419.                 CVisArea* pVisArea = (CVisArea*)Cry3DEngineBase::GetVisAreaManager()->GetVisAreaById(v);
  1420.                 if (!pVisArea)
  1421.                         break;
  1422.  
  1423.                 if (!Overlap::AABB_AABB(*pVisArea->GetAABBox(), m_nodeBox))
  1424.                         continue;
  1425.  
  1426.                 vCheckSumm += Vec3i(pVisArea->GetAABBox()->min * fPrecisioin);
  1427.                 vCheckSumm += Vec3i(pVisArea->GetAABBox()->max * fPrecisioin * 2);
  1428.         }
  1429.  
  1430.         return vCheckSumm;
  1431. }
  1432.  
  1433. void CSvoNode::UpdateNodeRenderDataPtrs()
  1434. {
  1435.         if (m_pSeg && m_ppChilds && m_pSeg->m_pBlockInfo && m_pSeg->m_nChildOffsetsDirty)
  1436.         {
  1437.                 ZeroStruct(m_pSeg->m_arrChildOffset);
  1438.  
  1439.                 for (int nChildId = 0; nChildId < 8; nChildId++)
  1440.                 {
  1441.                         CSvoNode* pChildNode = m_ppChilds[nChildId];
  1442.  
  1443.                         if (pChildNode && pChildNode->m_pSeg)
  1444.                         {
  1445.                                 pChildNode->UpdateNodeRenderDataPtrs();
  1446.  
  1447.                                 if (pChildNode->m_pSeg->CheckUpdateBrickRenderData(true))
  1448.                                 {
  1449.                                         m_pSeg->m_arrChildOffset[nChildId] = pChildNode->m_pSeg->m_nAllocatedAtlasOffset;
  1450.  
  1451.                                         int nAllChildsNum = 0;
  1452.                                         int nReadyChildsNum = 0;
  1453.  
  1454.                                         if (pChildNode->m_ppChilds)
  1455.                                         {
  1456.                                                 for (int nSubChildId = 0; nSubChildId < 8; nSubChildId++)
  1457.                                                 {
  1458.                                                         if (CSvoNode* pSubChildNode = pChildNode->m_ppChilds[nSubChildId])
  1459.                                                         {
  1460.                                                                 if (pSubChildNode->m_pSeg)
  1461.                                                                 {
  1462.                                                                         nAllChildsNum++;
  1463.                                                                         if (pSubChildNode->m_pSeg->CheckUpdateBrickRenderData(true))
  1464.                                                                                 nReadyChildsNum++;
  1465.                                                                 }
  1466.                                                         }
  1467.                                                 }
  1468.                                         }
  1469.  
  1470.                                         if (nAllChildsNum != nReadyChildsNum || !nAllChildsNum)
  1471.                                                 m_pSeg->m_arrChildOffset[nChildId] = -m_pSeg->m_arrChildOffset[nChildId];
  1472.                                 }
  1473.                         }
  1474.                         /*      else if(m_arrChildNotNeeded[nChildId])
  1475.                            {
  1476.                             m_pCloud->m_arrChildOffset[nChildId] = 0;//-3000;
  1477.                            }*/
  1478.                 }
  1479.  
  1480.                 if (m_pSeg->m_nChildOffsetsDirty == 2)
  1481.                         m_pSeg->UpdateNodeRenderData();
  1482.  
  1483.                 m_pSeg->m_nChildOffsetsDirty = 0;
  1484.         }
  1485. }
  1486.  
  1487. bool IntersectRayAABB(const Ray& r, const Vec3& m1, const Vec3& m2, float& tmin, float& tmax)
  1488. {
  1489.         float tymin, tymax, tzmin, tzmax;
  1490.         float flag = 1.0;
  1491.  
  1492.         if (r.direction.x >= 0)
  1493.         {
  1494.                 tmin = (m1.x - r.origin.x) / r.direction.x;
  1495.                 tmax = (m2.x - r.origin.x) / r.direction.x;
  1496.         }
  1497.         else
  1498.         {
  1499.                 tmin = (m2.x - r.origin.x) / r.direction.x;
  1500.                 tmax = (m1.x - r.origin.x) / r.direction.x;
  1501.         }
  1502.         if (r.direction.y >= 0)
  1503.         {
  1504.                 tymin = (m1.y - r.origin.y) / r.direction.y;
  1505.                 tymax = (m2.y - r.origin.y) / r.direction.y;
  1506.         }
  1507.         else
  1508.         {
  1509.                 tymin = (m2.y - r.origin.y) / r.direction.y;
  1510.                 tymax = (m1.y - r.origin.y) / r.direction.y;
  1511.         }
  1512.  
  1513.         if ((tmin > tymax) || (tymin > tmax)) flag = -1.0;
  1514.         if (tymin > tmin) tmin = tymin;
  1515.         if (tymax < tmax) tmax = tymax;
  1516.  
  1517.         if (r.direction.z >= 0)
  1518.         {
  1519.                 tzmin = (m1.z - r.origin.z) / r.direction.z;
  1520.                 tzmax = (m2.z - r.origin.z) / r.direction.z;
  1521.         }
  1522.         else
  1523.         {
  1524.                 tzmin = (m2.z - r.origin.z) / r.direction.z;
  1525.                 tzmax = (m1.z - r.origin.z) / r.direction.z;
  1526.         }
  1527.         if ((tmin > tzmax) || (tzmin > tmax)) flag = -1.0;
  1528.         if (tzmin > tmin) tmin = tzmin;
  1529.         if (tzmax < tmax) tmax = tzmax;
  1530.  
  1531.         return (flag > 0);
  1532. }
  1533.  
  1534. bool CSvoNode::IsStreamingInProgress()
  1535. {
  1536.         if (m_pSeg && m_pSeg->m_eStreamingStatus == ecss_InProgress)
  1537.                 return true;
  1538.  
  1539.         if (m_ppChilds)
  1540.                 for (int nChildId = 0; nChildId < 8; nChildId++)
  1541.                         if (m_ppChilds[nChildId] && m_ppChilds[nChildId]->IsStreamingInProgress())
  1542.                                 return true;
  1543.  
  1544.         return false;
  1545. }
  1546.  
  1547. void CSvoNode::GetTrisInAreaStats(int& nTrisCount, int& nVertCount, int& nTrisBytes, int& nVertBytes, int& nMaxVertPerArea, int& nMatsCount)
  1548. {
  1549.  
  1550.         if (m_pSeg && m_pSeg->m_pTrisInArea)
  1551.         {
  1552.                 if (m_pSeg && m_pSeg->m_pTrisInArea)
  1553.                 {
  1554.                         AUTO_READLOCK(m_pSeg->m_superMeshLock);
  1555.  
  1556.                         nTrisBytes += m_pSeg->m_pTrisInArea->ComputeSizeInMemory();
  1557.                         nVertBytes += m_pSeg->m_pVertInArea->ComputeSizeInMemory();
  1558.  
  1559.                         nTrisCount += m_pSeg->m_pTrisInArea->Count();
  1560.                         nVertCount += m_pSeg->m_pVertInArea->Count();
  1561.  
  1562.                         nMaxVertPerArea = max(nMaxVertPerArea, m_pSeg->m_pVertInArea->Count());
  1563.  
  1564.                         nMatsCount += m_pSeg->m_pMatsInArea->Count();
  1565.                 }
  1566.         }
  1567.         else if (m_ppChilds)
  1568.         {
  1569.                 for (int nChildId = 0; nChildId < 8; nChildId++)
  1570.                         if (m_ppChilds[nChildId])
  1571.                                 m_ppChilds[nChildId]->GetTrisInAreaStats(nTrisCount, nVertCount, nTrisBytes, nVertBytes, nMaxVertPerArea, nMatsCount);
  1572.         }
  1573. }
  1574.  
  1575. void CSvoNode::GetVoxSegMemUsage(int& nAllocated)
  1576. {
  1577.         if (m_pSeg)
  1578.         {
  1579.                 nAllocated += m_pSeg->m_nodeTrisAllMerged.capacity() * sizeof(int);
  1580.                 nAllocated += sizeof(*m_pSeg);
  1581.         }
  1582.  
  1583.         if (m_ppChilds)
  1584.         {
  1585.                 for (int nChildId = 0; nChildId < 8; nChildId++)
  1586.                         if (m_ppChilds[nChildId])
  1587.                                 m_ppChilds[nChildId]->GetVoxSegMemUsage(nAllocated);
  1588.         }
  1589. }
  1590.  
  1591. void CSvoNode::DeleteChilds()
  1592. {
  1593.         if (m_ppChilds)
  1594.         {
  1595.                 for (int nChildId = 0; nChildId < 8; nChildId++)
  1596.                         SAFE_DELETE(m_ppChilds[nChildId]);
  1597.                 SAFE_DELETE_ARRAY(m_ppChilds);
  1598.         }
  1599. }
  1600.  
  1601. bool CPointTreeNode::GetAllPointsInTheBox(const AABB& testBox, const AABB& nodeBox, PodArray<int>& arrIds)
  1602. {
  1603.         if (m_pPoints)
  1604.         {
  1605.                 // leaf
  1606.                 for (int s = 0; s < m_pPoints->Count(); s++)
  1607.                 {
  1608.                         Vec3& vPos = (*m_pPoints)[s].vPos;
  1609.  
  1610.                         if (testBox.IsContainPoint(vPos))
  1611.                         {
  1612.                                 arrIds.Add((*m_pPoints)[s].nId);
  1613.                         }
  1614.                 }
  1615.         }
  1616.  
  1617.         if (m_ppChilds)
  1618.         {
  1619.                 for (int nChildId = 0; nChildId < 8; nChildId++)
  1620.                 {
  1621.                         if (m_ppChilds[nChildId])
  1622.                         {
  1623.                                 AABB childBox = GetChildBBox(nChildId, nodeBox);
  1624.                                 if (Overlap::AABB_AABB(testBox, childBox))
  1625.                                         if (m_ppChilds[nChildId]->GetAllPointsInTheBox(testBox, childBox, arrIds))
  1626.                                                 return true;
  1627.                         }
  1628.                 }
  1629.         }
  1630.  
  1631.         return false;
  1632. }
  1633.  
  1634. bool CPointTreeNode::IsThereAnyPointInTheBox(const AABB& testBox, const AABB& nodeBox)
  1635. {
  1636.         if (m_pPoints)
  1637.         {
  1638.                 // leaf
  1639.                 for (int s = 0; s < m_pPoints->Count(); s++)
  1640.                 {
  1641.                         Vec3& vPos = (*m_pPoints)[s].vPos;
  1642.  
  1643.                         if (testBox.IsContainPoint(vPos))
  1644.                         {
  1645.                                 return true;
  1646.                         }
  1647.                 }
  1648.         }
  1649.  
  1650.         if (m_ppChilds)
  1651.         {
  1652.                 for (int nChildId = 0; nChildId < 8; nChildId++)
  1653.                 {
  1654.                         if (m_ppChilds[nChildId])
  1655.                         {
  1656.                                 AABB childBox = GetChildBBox(nChildId, nodeBox);
  1657.                                 if (Overlap::AABB_AABB(testBox, childBox))
  1658.                                         if (m_ppChilds[nChildId]->IsThereAnyPointInTheBox(testBox, childBox))
  1659.                                                 return true;
  1660.                         }
  1661.                 }
  1662.         }
  1663.  
  1664.         return false;
  1665. }
  1666.  
  1667. bool CPointTreeNode::TryInsertPoint(int nId, const Vec3& vPos, const AABB& nodeBox, int nRecursionLevel)
  1668. {
  1669.         if (nRecursionLevel >= 7)
  1670.         {
  1671.                 if (!m_pPoints)
  1672.                         m_pPoints = new PodArray<SPointInfo>;
  1673.                 SPointInfo info;
  1674.                 info.vPos = vPos;
  1675.                 info.nId = nId;
  1676.                 m_pPoints->Add(info);
  1677.                 return true;
  1678.         }
  1679.  
  1680.         Vec3 vNodeCenter = nodeBox.GetCenter();
  1681.  
  1682.         int nChildId =
  1683.           ((vPos.x >= vNodeCenter.x) ? 4 : 0) |
  1684.           ((vPos.y >= vNodeCenter.y) ? 2 : 0) |
  1685.           ((vPos.z >= vNodeCenter.z) ? 1 : 0);
  1686.  
  1687.         if (!m_ppChilds)
  1688.         {
  1689.                 m_ppChilds = new CPointTreeNode*[8];
  1690.                 memset(m_ppChilds, 0, sizeof(m_ppChilds[0]) * 8);
  1691.         }
  1692.  
  1693.         AABB childBox = GetChildBBox(nChildId, nodeBox);
  1694.  
  1695.         if (!m_ppChilds[nChildId])
  1696.                 m_ppChilds[nChildId] = new CPointTreeNode();
  1697.  
  1698.         return m_ppChilds[nChildId]->TryInsertPoint(nId, vPos, childBox, nRecursionLevel + 1);
  1699. }
  1700.  
  1701. void CPointTreeNode::Clear()
  1702. {
  1703.         if (m_ppChilds)
  1704.                 for (int nChildId = 0; nChildId < 8; nChildId++)
  1705.                         SAFE_DELETE(m_ppChilds[nChildId]);
  1706.         SAFE_DELETE_ARRAY(m_ppChilds);
  1707.         SAFE_DELETE_ARRAY(m_pPoints);
  1708. }
  1709.  
  1710. AABB CPointTreeNode::GetChildBBox(int nChildId, const AABB& nodeBox)
  1711. {
  1712.         int x = (nChildId / 4);
  1713.         int y = (nChildId - x * 4) / 2;
  1714.         int z = (nChildId - x * 4 - y * 2);
  1715.         Vec3 vSize = nodeBox.GetSize() * 0.5f;
  1716.         Vec3 vOffset = vSize;
  1717.         vOffset.x *= x;
  1718.         vOffset.y *= y;
  1719.         vOffset.z *= z;
  1720.         AABB childBox;
  1721.         childBox.min = nodeBox.min + vOffset;
  1722.         childBox.max = childBox.min + vSize;
  1723.         return childBox;
  1724. }
  1725.  
  1726. bool CSvoEnv::GetSvoStaticTextures(I3DEngine::SSvoStaticTexInfo& svoInfo, PodArray<I3DEngine::SLightTI>* pLightsTI_S, PodArray<I3DEngine::SLightTI>* pLightsTI_D)
  1727. {
  1728.         AUTO_LOCK(m_csLockTree);
  1729.  
  1730.         svoInfo.pTexTree = GetRenderer()->EF_GetTextureByID(m_nTexNodePoolId);
  1731.         svoInfo.pTexOpac = GetRenderer()->EF_GetTextureByID(m_nTexOpasPoolId);
  1732.  
  1733.         #ifdef FEATURE_SVO_GI_ALLOW_HQ
  1734.                 #ifdef FEATURE_SVO_GI_USE_MESH_RT
  1735.         svoInfo.pTexTris = GetRenderer()->EF_GetTextureByID(m_nTexTrisPoolId);
  1736.                 #endif
  1737.         svoInfo.pTexRgb0 = GetRenderer()->EF_GetTextureByID(m_nTexRgb0PoolId);
  1738.         svoInfo.pTexRgb1 = GetRenderer()->EF_GetTextureByID(m_nTexRgb1PoolId);
  1739.         svoInfo.pTexDynl = GetRenderer()->EF_GetTextureByID(m_nTexDynlPoolId);
  1740.         svoInfo.pTexRgb2 = GetRenderer()->EF_GetTextureByID(m_nTexRgb2PoolId);
  1741.         svoInfo.pTexRgb3 = GetRenderer()->EF_GetTextureByID(m_nTexRgb3PoolId);
  1742.         svoInfo.pTexRgb4 = GetRenderer()->EF_GetTextureByID(m_nTexRgb4PoolId);
  1743.         svoInfo.pTexNorm = GetRenderer()->EF_GetTextureByID(m_nTexNormPoolId);
  1744.         svoInfo.pTexAldi = GetRenderer()->EF_GetTextureByID(m_nTexAldiPoolId);
  1745.         svoInfo.pTexTriA = GetRenderer()->EF_GetTextureByID(gSvoEnv->m_arrRTPoolTris.m_nTexId);
  1746.         svoInfo.pTexTexA = GetRenderer()->EF_GetTextureByID(gSvoEnv->m_arrRTPoolTexs.m_nTexId);
  1747.         svoInfo.pTexIndA = GetRenderer()->EF_GetTextureByID(gSvoEnv->m_arrRTPoolInds.m_nTexId);
  1748.         svoInfo.pGlobalSpecCM = m_pGlobalSpecCM;
  1749.         #endif
  1750.  
  1751.         svoInfo.fGlobalSpecCM_Mult = m_fGlobalSpecCM_Mult;
  1752.  
  1753.         svoInfo.nTexDimXY = CVoxelSegment::nVoxTexPoolDimXY;
  1754.         svoInfo.nTexDimZ = CVoxelSegment::nVoxTexPoolDimZ;
  1755.         svoInfo.nBrickSize = nVoxTexMaxDim;
  1756.  
  1757.         svoInfo.bSvoReady = (m_fStreamingStartTime < 0);
  1758.         svoInfo.bSvoFreeze = (m_fSvoFreezeTime >= 0);
  1759.  
  1760.         ZeroStruct(svoInfo.arrPortalsPos);
  1761.         ZeroStruct(svoInfo.arrPortalsDir);
  1762.         if (GetCVars()->e_svoTI_PortalsDeform || GetCVars()->e_svoTI_PortalsInject)
  1763.         {
  1764.                 if (IVisArea* pCurVisArea = GetVisAreaManager()->GetCurVisArea())
  1765.                 {
  1766.                         PodArray<IVisArea*> visitedAreas;
  1767.                         pCurVisArea->FindSurroundingVisArea(2, true, &visitedAreas, 32);
  1768.  
  1769.                         int nPortalCounter = 0;
  1770.                         for (int nAreaID = 0; nAreaID < visitedAreas.Count(); nAreaID++)
  1771.                         {
  1772.                                 IVisArea* pPortal = visitedAreas[nAreaID];
  1773.  
  1774.                                 if (!pPortal || nPortalCounter >= SVO_MAX_PORTALS)
  1775.                                         break;
  1776.  
  1777.                                 if (!pPortal->IsPortal())
  1778.                                         continue;
  1779.  
  1780.                                 if (!pPortal->IsConnectedToOutdoor())
  1781.                                         continue;
  1782.  
  1783.                                 AABB boxEx = *pPortal->GetAABBox();
  1784.                                 boxEx.Expand(Vec3(GetCVars()->e_svoTI_ConeMaxLength, GetCVars()->e_svoTI_ConeMaxLength, GetCVars()->e_svoTI_ConeMaxLength));
  1785.                                 if (!gEnv->pSystem->GetViewCamera().IsAABBVisible_E(boxEx))
  1786.                                         continue;
  1787.  
  1788.                                 svoInfo.arrPortalsPos[nPortalCounter] = Vec4(pPortal->GetAABBox()->GetCenter(), pPortal->GetAABBox()->GetRadius());
  1789.                                 svoInfo.arrPortalsDir[nPortalCounter] = Vec4(((CVisArea*)pCurVisArea)->GetConnectionNormal((CVisArea*)pPortal), 0);
  1790.  
  1791.                                 nPortalCounter++;
  1792.                         }
  1793.                 }
  1794.         }
  1795.  
  1796.         ZeroStruct(svoInfo.arrAnalyticalOccluders);
  1797.         for (int nStage = 0; nStage < 2; nStage++)
  1798.         {
  1799.                 if (m_AnalyticalOccluders[nStage].Count())
  1800.                 {
  1801.                         uint32 bytesToCopy = min((unsigned int)sizeof(svoInfo.arrAnalyticalOccluders[nStage]), m_AnalyticalOccluders[nStage].GetDataSize());
  1802.                         memcpy(&svoInfo.arrAnalyticalOccluders[nStage][0], m_AnalyticalOccluders[nStage].GetElements(), bytesToCopy);
  1803.                 }
  1804.         }
  1805.  
  1806.         svoInfo.vSvoOriginAndSize = m_vSvoOriginAndSize;
  1807.  
  1808.         if (GetCVars()->e_svoTI_UseTODSkyColor)
  1809.         {
  1810.                 ITimeOfDay::SVariableInfo varCol, varMul;
  1811.                 Get3DEngine()->GetTimeOfDay()->GetVariableInfo(ITimeOfDay::PARAM_FOG_COLOR2, varCol);
  1812.                 Get3DEngine()->GetTimeOfDay()->GetVariableInfo(ITimeOfDay::PARAM_FOG_COLOR2_MULTIPLIER, varMul);
  1813.                 svoInfo.vSkyColorTop = Vec3(varCol.fValue[0] * varMul.fValue[0], varCol.fValue[1] * varMul.fValue[0], varCol.fValue[2] * varMul.fValue[0]);
  1814.                 Get3DEngine()->GetTimeOfDay()->GetVariableInfo(ITimeOfDay::PARAM_FOG_COLOR, varCol);
  1815.                 Get3DEngine()->GetTimeOfDay()->GetVariableInfo(ITimeOfDay::PARAM_FOG_COLOR_MULTIPLIER, varMul);
  1816.                 svoInfo.vSkyColorBottom = Vec3(varCol.fValue[0] * varMul.fValue[0], varCol.fValue[1] * varMul.fValue[0], varCol.fValue[2] * varMul.fValue[0]);
  1817.  
  1818.                 float fAver = (svoInfo.vSkyColorTop.x + svoInfo.vSkyColorTop.y + svoInfo.vSkyColorTop.z) / 3;
  1819.                 svoInfo.vSkyColorTop.SetLerp(Vec3(fAver, fAver, fAver), svoInfo.vSkyColorTop, GetCVars()->e_svoTI_UseTODSkyColor);
  1820.                 fAver = (svoInfo.vSkyColorBottom.x + svoInfo.vSkyColorBottom.y + svoInfo.vSkyColorBottom.z) / 3;
  1821.                 svoInfo.vSkyColorBottom.SetLerp(Vec3(fAver, fAver, fAver), svoInfo.vSkyColorBottom, GetCVars()->e_svoTI_UseTODSkyColor);
  1822.         }
  1823.         else
  1824.         {
  1825.                 svoInfo.vSkyColorBottom = svoInfo.vSkyColorTop = Vec3(1.f, 1.f, 1.f);
  1826.         }
  1827.  
  1828.         *pLightsTI_S = m_lightsTI_S;
  1829.         *pLightsTI_D = m_lightsTI_D;
  1830.  
  1831.         return /*!GetCVars()->e_svoQuad && */ svoInfo.pTexTree != 0;
  1832. }
  1833.  
  1834. void CSvoEnv::GetSvoBricksForUpdate(PodArray<I3DEngine::SSvoNodeInfo>& arrNodeInfo, float fNodeSize, PodArray<SVF_P3F_C4B_T2F>* pVertsOut)
  1835. {
  1836.         FUNCTION_PROFILER_3DENGINE;
  1837.  
  1838.         AUTO_LOCK(m_csLockTree);
  1839.  
  1840.         arrNodeInfo.Clear();
  1841.  
  1842.         if (!CVoxelSegment::m_pBlockPacker)
  1843.                 return;
  1844.  
  1845.         if (pVertsOut)
  1846.                 *pVertsOut = m_arrSvoProxyVertices;
  1847.  
  1848.         if (!GetCVars()->e_svoTI_Active && !GetCVars()->e_svoDVR)
  1849.                 return;
  1850.  
  1851.         //  uint nOldestVisFrameId[4] = { ~0, ~0, ~0, ~0 };
  1852.         //  const uint nMaxAllowedFrameId = GetCurrPassMainFrameID()-16;
  1853.         const uint nNumBlocks = CVoxelSegment::m_pBlockPacker->GetNumBlocks();
  1854.  
  1855.         bool bSyncAll = 1;
  1856.  
  1857.         if (fNodeSize == 0)
  1858.         {
  1859.                 gSvoEnv->m_nDynNodeCounter = 0;
  1860.  
  1861.                 double fCheckVal = 0;
  1862.                 fCheckVal += GetCVars()->e_svoTI_DiffuseConeWidth;
  1863.                 fCheckVal += GetCVars()->e_svoTI_InjectionMultiplier;
  1864.                 fCheckVal += GetCVars()->e_svoTI_PropagationBooster;
  1865.                 fCheckVal += GetCVars()->e_svoTI_NumberOfBounces;
  1866.                 fCheckVal += GetCVars()->e_svoTI_DynLights;
  1867.                 fCheckVal += GetCVars()->e_svoTI_Saturation;
  1868.                 fCheckVal += GetCVars()->e_svoTI_SkyColorMultiplier;
  1869.                 fCheckVal += GetCVars()->e_svoTI_ConeMaxLength;
  1870.                 fCheckVal += GetCVars()->e_svoTI_DiffuseBias * 10;
  1871.                 fCheckVal += GetCVars()->e_svoMinNodeSize;
  1872.                 fCheckVal += GetCVars()->e_svoMaxNodeSize;
  1873.                 fCheckVal += (float)(m_fStreamingStartTime < 0);
  1874.                 fCheckVal += GetCVars()->e_Sun;
  1875.                 static int e_svoTI_Troposphere_Active_Max = 0;
  1876.                 e_svoTI_Troposphere_Active_Max = max(e_svoTI_Troposphere_Active_Max, GetCVars()->e_svoTI_Troposphere_Active);
  1877.                 fCheckVal += (float)e_svoTI_Troposphere_Active_Max;
  1878.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_Brightness;
  1879.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_Ground_Height;
  1880.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_Layer0_Height;
  1881.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_Layer1_Height;
  1882.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_Snow_Height;
  1883.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_Layer0_Rand;
  1884.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_Layer1_Rand;
  1885.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_Layer0_Dens * 10;
  1886.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_Layer1_Dens * 10;
  1887.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_CloudGen_Height;
  1888.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_CloudGen_Freq;
  1889.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_CloudGen_FreqStep;
  1890.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_CloudGen_Scale;
  1891.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_CloudGenTurb_Freq;
  1892.                 fCheckVal += GetCVars()->e_svoTI_Troposphere_CloudGenTurb_Scale;
  1893.                 fCheckVal += GetCVars()->e_svoTI_HalfresKernelSecondary;
  1894.                 fCheckVal += GetCVars()->e_svoTI_Diffuse_Cache;
  1895.                 fCheckVal += GetCVars()->e_svoTI_PortalsInject * 10;
  1896.                 fCheckVal += GetCVars()->e_svoTI_SunRSMInject;
  1897.                 fCheckVal += GetCVars()->e_svoTI_EmissiveMultiplier;
  1898.                 fCheckVal += GetCVars()->e_svoTI_PointLightsMultiplier;
  1899.  
  1900.                 //              fCheckVal += int(Get3DEngine()->GetSunDir().x*10);
  1901.                 //      fCheckVal += int(Get3DEngine()->GetSunDir().y*10);
  1902.                 //fCheckVal += int(Get3DEngine()->GetSunDir().z*10);
  1903.  
  1904.                 if (m_prevCheckVal == -1000000)
  1905.                         m_prevCheckVal = fCheckVal;
  1906.  
  1907.                 bSyncAll = (m_prevCheckVal != (fCheckVal));
  1908.  
  1909.                 {
  1910.                         static int nPrevFlagAsync = GetCVars()->e_svoTI_UpdateLighting;
  1911.                         if (GetCVars()->e_svoTI_UpdateLighting && !nPrevFlagAsync)
  1912.                                 bSyncAll = true;
  1913.                         nPrevFlagAsync = GetCVars()->e_svoTI_UpdateLighting;
  1914.                 }
  1915.  
  1916.                 {
  1917.                         static int nPrevFlagAsync = (gSvoEnv->m_fSvoFreezeTime <= 0);
  1918.                         if ((gSvoEnv->m_fSvoFreezeTime <= 0) && !nPrevFlagAsync)
  1919.                         {
  1920.                                 bSyncAll = true;
  1921.                                 gSvoEnv->m_fSvoFreezeTime = -1;
  1922.                         }
  1923.                         nPrevFlagAsync = (gSvoEnv->m_fSvoFreezeTime <= 0);
  1924.                 }
  1925.  
  1926.                 m_prevCheckVal = fCheckVal;
  1927.  
  1928.                 if (bSyncAll)
  1929.                         PrintMessage("SVO radiance full update");
  1930.  
  1931.                 bool bEditing = gEnv->IsEditing();
  1932.  
  1933.                 if (GetCVars()->e_svoTI_UpdateLighting && GetCVars()->e_svoTI_IntegrationMode)
  1934.                 {
  1935.                         int nAutoUpdateVoxNum = 0;
  1936.  
  1937.                         int nMaxVox = GetCVars()->e_svoTI_Reflect_Vox_Max * (int)30 / (int)max(30.f, gEnv->pTimer->GetFrameRate());
  1938.                         int nMaxVoxEdit = GetCVars()->e_svoTI_Reflect_Vox_MaxEdit * (int)30 / (int)max(30.f, gEnv->pTimer->GetFrameRate());
  1939.  
  1940.                         for (uint n = 0; n < nNumBlocks; n++)
  1941.                         {
  1942.                                 static uint nAutoBlockId = 0;
  1943.                                 if (nAutoBlockId >= nNumBlocks)
  1944.                                         nAutoBlockId = 0;
  1945.  
  1946.                                 if (SBlockMinMax* pBlock = CVoxelSegment::m_pBlockPacker->GetBlockInfo(nAutoBlockId))
  1947.                                 {
  1948.                                         CVoxelSegment* pSeg = (CVoxelSegment*)pBlock->m_pUserData;
  1949.  
  1950.                                         if ((pSeg->GetBoxSize() >= fNodeSize && pSeg->GetBoxSize() <= GetCVars()->e_svoMaxNodeSize) || !fNodeSize)
  1951.                                                 if (pSeg->m_pNode->m_nRequestSegmentUpdateFrametId < GetCurrPassMainFrameID() - 30)
  1952.                                                 {
  1953.                                                         if (nAutoUpdateVoxNum && (nAutoUpdateVoxNum + (int(sqrt((float)pSeg->m_nVoxNum)) + GetCVars()->e_svoTI_Reflect_Vox_Max_Overhead) > nMaxVox))
  1954.                                                         {
  1955.                                                                 if (bEditing)
  1956.                                                                 {
  1957.                                                                         if (pSeg->m_bStatLightsChanged)
  1958.                                                                                 if ((pSeg->GetBoxSize() >= fNodeSize && pSeg->GetBoxSize() <= GetCVars()->e_svoMaxNodeSize) || !fNodeSize)
  1959.                                                                                 //if(pSeg->m_pNode->m_nRequestBrickUpdateFrametId < GetCurrPassMainFrameID()-30)
  1960.                                                                                 {
  1961.                                                                                         if (nAutoUpdateVoxNum && (nAutoUpdateVoxNum + (int(sqrt((float)pSeg->m_nVoxNum)) + GetCVars()->e_svoTI_Reflect_Vox_Max_Overhead) > nMaxVoxEdit))
  1962.                                                                                         {
  1963.                                                                                         }
  1964.                                                                                         else
  1965.                                                                                         {
  1966.                                                                                                 pSeg->m_pNode->m_nRequestSegmentUpdateFrametId = max(pSeg->m_pNode->m_nRequestSegmentUpdateFrametId, GetCurrPassMainFrameID());
  1967.                                                                                                 nAutoUpdateVoxNum += (int(sqrt((float)pSeg->m_nVoxNum)) + GetCVars()->e_svoTI_Reflect_Vox_Max_Overhead);
  1968.                                                                                         }
  1969.                                                                                 }
  1970.                                                                 }
  1971.                                                                 else
  1972.                                                                         break;
  1973.                                                         }
  1974.                                                         else
  1975.                                                         {
  1976.                                                                 pSeg->m_pNode->m_nRequestSegmentUpdateFrametId = max(pSeg->m_pNode->m_nRequestSegmentUpdateFrametId, GetCurrPassMainFrameID());
  1977.                                                                 nAutoUpdateVoxNum += (int(sqrt((float)pSeg->m_nVoxNum)) + GetCVars()->e_svoTI_Reflect_Vox_Max_Overhead);
  1978.                                                         }
  1979.                                                 }
  1980.                                 }
  1981.  
  1982.                                 nAutoBlockId++;
  1983.                         }
  1984.                 }
  1985.         }
  1986.  
  1987.         static uint nBlockId = 0;
  1988.  
  1989.         uint nMaxUpdateBlocks = (bSyncAll || (GetCVars()->e_svoDVR != 10)) ? nNumBlocks : (nNumBlocks / 16 + 1);
  1990.  
  1991.         m_nDynNodeCounter_DYNL = 0;
  1992.  
  1993.         for (uint nBl = 0; nBl < nMaxUpdateBlocks; nBl++)
  1994.         {
  1995.                 nBlockId++;
  1996.                 if (nBlockId >= nNumBlocks)
  1997.                         nBlockId = 0;
  1998.  
  1999.                 if (SBlockMinMax* pBlock = CVoxelSegment::m_pBlockPacker->GetBlockInfo(nBlockId))
  2000.                 {
  2001.                         CVoxelSegment* pSeg = (CVoxelSegment*)pBlock->m_pUserData;
  2002.  
  2003.                         //                      if( ((GetMainFrameID()%nNumBlocks)&63) == (nBlockId&63) && pSeg->m_pNode->m_nRequestBrickUpdateFrametId>0 && GetCVars()->e_svoDVR )
  2004.                         //                      pSeg->m_pNode->m_nRequestBrickUpdateFrametId = GetMainFrameID();
  2005.  
  2006.                         if (pSeg->m_pNode->m_nRequestSegmentUpdateFrametId >= GetCurrPassMainFrameID() || bSyncAll || pSeg->m_bStatLightsChanged)
  2007.                         {
  2008.                                 if (fNodeSize == 0)
  2009.                                         gSvoEnv->m_nDynNodeCounter++;
  2010.  
  2011.                                 if ((pSeg->GetBoxSize() >= fNodeSize && pSeg->GetBoxSize() <= GetCVars()->e_svoMaxNodeSize) || !fNodeSize)
  2012.                                 //                                      if( pSeg->GetBoxSize() <= GetCVars()->e_svoMaxNodeSize )
  2013.                                 {
  2014.                                         I3DEngine::SSvoNodeInfo nodeInfo;
  2015.  
  2016.                                         nodeInfo.wsBox.min = pSeg->m_boxOS.min + pSeg->m_vSegOrigin;
  2017.                                         nodeInfo.wsBox.max = pSeg->m_boxOS.max + pSeg->m_vSegOrigin;
  2018.  
  2019.                                         nodeInfo.tcBox.min.Set((float)pBlock->m_dwMinX / (float)nAtlasDimMaxXY, (float)pBlock->m_dwMinY / (float)nAtlasDimMaxXY, (float)pBlock->m_dwMinZ / (float)nAtlasDimMaxZ);
  2020.                                         nodeInfo.tcBox.max.Set((float)pBlock->m_dwMaxX / (float)nAtlasDimMaxXY, (float)pBlock->m_dwMaxY / (float)nAtlasDimMaxXY, (float)pBlock->m_dwMaxZ / (float)nAtlasDimMaxZ);
  2021.  
  2022.                                         nodeInfo.nAtlasOffset = pSeg->m_nAllocatedAtlasOffset;
  2023.  
  2024.                                         if (fNodeSize)
  2025.                                         {
  2026.                                                 if (nodeInfo.wsBox.GetDistance(Get3DEngine()->GetRenderingCamera().GetPosition()) > 24.f)//nodeInfo.wsBox.GetSize().z)
  2027.                                                         continue;
  2028.  
  2029.                                                 //                                              if(!Overlap::AABB_AABB(nodeInfo.wsBox, m_aabbLightsTI_D))
  2030.                                                 //                                              continue;
  2031.  
  2032.                                                 AABB wsBoxEx = nodeInfo.wsBox;
  2033.                                                 wsBoxEx.Expand(Vec3(2, 2, 2));
  2034.                                                 if (!gEnv->pSystem->GetViewCamera().IsAABBVisible_F(wsBoxEx))
  2035.                                                         continue;
  2036.  
  2037.                                                 m_nDynNodeCounter_DYNL++;
  2038.                                         }
  2039.  
  2040.                                         pSeg->m_bStatLightsChanged = 0;
  2041.  
  2042.                                         arrNodeInfo.Add(nodeInfo);
  2043.                                 }
  2044.                         }
  2045.                 }
  2046.         }
  2047. }
  2048.  
  2049. void CSvoEnv::DetectMovement_StaticGeom()
  2050. {
  2051.         FUNCTION_PROFILER_3DENGINE;
  2052.  
  2053.         if (!CVoxelSegment::m_pBlockPacker)
  2054.                 return;
  2055.  
  2056.         if (!GetCVars()->e_svoTI_Apply)
  2057.                 return;
  2058.  
  2059.         const uint nNumBlocks = CVoxelSegment::m_pBlockPacker->GetNumBlocks();
  2060.         for (uint nBlockId = 0; nBlockId < nNumBlocks; nBlockId++)
  2061.         {
  2062.                 if (SBlockMinMax* pBlock = CVoxelSegment::m_pBlockPacker->GetBlockInfo(nBlockId))
  2063.                 {
  2064.                         CVoxelSegment* pSeg = (CVoxelSegment*)pBlock->m_pUserData;
  2065.  
  2066.                         Vec3i vCheckSumm = pSeg->m_pNode->GetStatGeomCheckSumm();
  2067.  
  2068.                         //if( !pSeg->m_vStaticGeomCheckSumm.IsEquivalent(vCheckSumm, 2) )
  2069.                         {
  2070.                                 if (pSeg->m_eStreamingStatus != ecss_NotLoaded)
  2071.                                 {
  2072.                                         CSvoNode* pNode = pSeg->m_pNode;
  2073.                                         while (pNode)
  2074.                                         {
  2075.                                                 pNode->m_bForceRecreate = true;
  2076.                                                 if (pNode->m_nodeBox.GetSize().z >= GetCVars()->e_svoMaxNodeSize)
  2077.                                                         break;
  2078.                                                 pNode = pNode->m_pParent;
  2079.                                         }
  2080.                                 }
  2081.  
  2082.                                 pSeg->m_vStaticGeomCheckSumm = vCheckSumm;
  2083.                         }
  2084.                 }
  2085.         }
  2086. }
  2087.  
  2088. void CSvoEnv::DetectMovement_StatLights()
  2089. {
  2090.         FUNCTION_PROFILER_3DENGINE;
  2091.  
  2092.         if (!CVoxelSegment::m_pBlockPacker)
  2093.                 return;
  2094.  
  2095.         if (!GetCVars()->e_svoTI_Apply)
  2096.                 return;
  2097.  
  2098.         // count stats
  2099.         const int nDataSizeStatsScale = 4;
  2100.         CVoxelSegment::m_nPoolUsageItems = 0;
  2101.         CVoxelSegment::m_nPoolUsageBytes = 0;
  2102.  
  2103.         const uint nNumBlocks = CVoxelSegment::m_pBlockPacker->GetNumBlocks();
  2104.         for (uint nBlockId = 0; nBlockId < nNumBlocks; nBlockId++)
  2105.         {
  2106.                 if (SBlockMinMax* pBlock = CVoxelSegment::m_pBlockPacker->GetBlockInfo(nBlockId))
  2107.                 {
  2108.                         CVoxelSegment::m_nPoolUsageItems++;
  2109.                         CVoxelSegment::m_nPoolUsageBytes += nDataSizeStatsScale * pBlock->m_nDataSize;
  2110.  
  2111.                         CVoxelSegment* pSeg = (CVoxelSegment*)pBlock->m_pUserData;
  2112.  
  2113.                         float fNodeSize = pSeg->GetBoxSize();
  2114.  
  2115.                         PodArray<IRenderNode*> lstObjects;
  2116.                         AABB boxEx = pSeg->m_pNode->m_nodeBox;
  2117.                         float fBorder = fNodeSize / 4.f + GetCVars()->e_svoTI_ConeMaxLength * max(0, GetCVars()->e_svoTI_NumberOfBounces - 1);
  2118.                         boxEx.Expand(Vec3(fBorder, fBorder, fBorder));
  2119.                         Cry3DEngineBase::Get3DEngine()->GetObjectsByTypeGlobal(lstObjects, eERType_Light, &boxEx);
  2120.                         Cry3DEngineBase::Get3DEngine()->GetVisAreaManager()->GetObjectsByType(lstObjects, eERType_Light, &boxEx);
  2121.  
  2122.                         float fPrecisioin = 1000.f;
  2123.                         Vec3i vCheckSumm(0, 0, 0);
  2124.  
  2125.                         for (int i = 0; i < lstObjects.Count(); i++)
  2126.                         {
  2127.                                 IRenderNode* pNode = lstObjects[i];
  2128.  
  2129.                                 if (pNode->GetGIMode() == IRenderNode::eGM_StaticVoxelization)
  2130.                                 {
  2131.                                         if (pNode->GetRenderNodeType() == eERType_Light)
  2132.                                         {
  2133.                                                 ILightSource* pLS = (ILightSource*)pNode;
  2134.  
  2135.                                                 CDLight& m_light = pLS->GetLightProperties();
  2136.  
  2137.                                                 if (!Overlap::Sphere_AABB(Sphere(m_light.m_BaseOrigin, m_light.m_fBaseRadius), pSeg->m_pNode->m_nodeBox))
  2138.                                                         continue;
  2139.  
  2140.                                                 if ((m_light.m_Flags & DLF_PROJECT) && (m_light.m_fLightFrustumAngle < 90.f) && m_light.m_pLightImage)
  2141.                                                 {
  2142.                                                         CCamera lightCam = gEnv->pSystem->GetViewCamera();
  2143.                                                         lightCam.SetPositionNoUpdate(m_light.m_Origin);
  2144.                                                         Matrix34 entMat = ((ILightSource*)(m_light.m_pOwner))->GetMatrix();
  2145.                                                         entMat.OrthonormalizeFast();
  2146.                                                         Matrix33 matRot = Matrix33::CreateRotationVDir(entMat.GetColumn(0));
  2147.                                                         lightCam.SetMatrixNoUpdate(Matrix34(matRot, m_light.m_Origin));
  2148.                                                         lightCam.SetFrustum(1, 1, (m_light.m_fLightFrustumAngle * 2) / 180.0f * gf_PI, 0.1f, m_light.m_fRadius);
  2149.                                                         if (!lightCam.IsAABBVisible_F(pSeg->m_pNode->m_nodeBox))
  2150.                                                                 continue;
  2151.  
  2152.                                                         vCheckSumm.x += int(m_light.m_fLightFrustumAngle);
  2153.                                                         vCheckSumm += Vec3i(entMat.GetColumn(0) * 10.f);
  2154.                                                 }
  2155.  
  2156.                                                 if (m_light.m_Flags & DLF_CASTSHADOW_MAPS)
  2157.                                                         vCheckSumm.z += 10;
  2158.  
  2159.                                                 vCheckSumm += Vec3i(m_light.m_BaseColor.toVec3() * 50.f);
  2160.  
  2161.                                                 if (m_light.m_Flags & DLF_SUN)
  2162.                                                 {
  2163.                                                         //                                                      vCheckSumm.x += int(Get3DEngine()->GetSunDir().x*50);
  2164.                                                         //                                              vCheckSumm.y += int(Get3DEngine()->GetSunDir().y*50);
  2165.                                                         //                                      vCheckSumm.z += int(Get3DEngine()->GetSunDir().z*50);
  2166.                                                         continue;
  2167.                                                 }
  2168.                                         }
  2169.  
  2170.                                         AABB box = pNode->GetBBox();
  2171.                                         vCheckSumm += Vec3i(box.min * fPrecisioin);
  2172.                                         vCheckSumm += Vec3i(box.max * fPrecisioin * 2);
  2173.                                 }
  2174.                         }
  2175.  
  2176.                         if (!vCheckSumm.IsZero())
  2177.                         {
  2178.                                 vCheckSumm.x += (int)GetCVars()->e_svoVoxNodeRatio;
  2179.                                 vCheckSumm.y += (int)GetCVars()->e_svoVoxDistRatio;
  2180.                         }
  2181.  
  2182.                         if (!pSeg->m_vStatLightsCheckSumm.IsEquivalent(vCheckSumm, 2))
  2183.                         {
  2184.                                 //                              if(!pSeg->m_vStatLightsCheckSumm.IsZero())
  2185.                                 pSeg->m_bStatLightsChanged = 1;
  2186.                                 pSeg->m_vStatLightsCheckSumm = vCheckSumm;
  2187.                         }
  2188.                 }
  2189.         }
  2190. }
  2191.  
  2192. void CSvoEnv::StartupStreamingTimeTest(bool bDone)
  2193. {
  2194.         if (m_fSvoFreezeTime > 0 && bDone && m_bStreamingDonePrev)
  2195.         {
  2196.                 PrintMessage("SVO update finished in %.1f sec (%d / %d nodes, %d K tris)",
  2197.                              gEnv->pTimer->GetAsyncCurTime() - m_fSvoFreezeTime, m_arrVoxelizeMeshesCounter[0], m_arrVoxelizeMeshesCounter[1], CVoxelSegment::m_nVoxTrisCounter / 1000);
  2198.                 m_fSvoFreezeTime = 0;
  2199.  
  2200.                 if (GetCVars()->e_svoDebug)
  2201.                 {
  2202.                         AUTO_MODIFYLOCK(CVoxelSegment::m_cgfTimeStatsLock);
  2203.                         PrintMessage("Voxelization time spend per CFG:");
  2204.                         for (auto it = CVoxelSegment::m_cgfTimeStats.begin(); it != CVoxelSegment::m_cgfTimeStats.end(); ++it)
  2205.                                 if (it->second > 1.f)
  2206.                                         PrintMessage("  %4.1f sec %s", it->second, it->first->GetFilePath());
  2207.                 }
  2208.         }
  2209.  
  2210.         if (m_fStreamingStartTime == 0)
  2211.         {
  2212.                 m_fStreamingStartTime = Cry3DEngineBase::GetTimer()->GetAsyncCurTime();
  2213.         }
  2214.         else if (m_fStreamingStartTime > 0 && bDone && m_bStreamingDonePrev)
  2215.         {
  2216.                 //              float fTime = Cry3DEngineBase::GetTimer()->GetAsyncCurTime();
  2217.                 //              PrintMessage("SVO initialization finished in %.1f sec (%d K tris)",
  2218.                 //              fTime - m_fStreamingStartTime, CVoxelSegment::m_nVoxTrisCounter/1000);
  2219.  
  2220.                 m_fStreamingStartTime = -1;
  2221.  
  2222.                 OnLevelGeometryChanged();
  2223.  
  2224.                 GetCVars()->e_svoMaxBrickUpdates = 4;
  2225.                 GetCVars()->e_svoMaxStreamRequests = 4;
  2226.  
  2227.                 int nGpuMax = nAtlasDimBriXY * nAtlasDimBriXY * nAtlasDimBriZ;
  2228.                 GetCVars()->e_svoMaxBricksOnCPU = nGpuMax * 3 / 2;
  2229.  
  2230.                 //              if(m_pTree)
  2231.                 //              m_pTree->UpdateTerrainNormals();
  2232.         }
  2233.  
  2234.         m_bStreamingDonePrev = bDone;
  2235. }
  2236.  
  2237. void CSvoEnv::OnLevelGeometryChanged()
  2238. {
  2239.  
  2240. }
  2241.  
  2242. int CSvoEnv::GetWorstPointInSubSet(const int nStart, const int nEnd)
  2243. {
  2244.         int p0 = -1;
  2245.  
  2246.         float fMinAverDist = 100000000;
  2247.  
  2248.         for (int i = nStart; i < nEnd; i++)
  2249.         {
  2250.                 float fAverDist = 0;
  2251.  
  2252.                 for (int j = 0; j < nRaysNum; j++)
  2253.                 {
  2254.                         float fDist = sqrt(sqrt(pKernelPoints[i].GetSquaredDistance2D(pKernelPoints[j])));
  2255.  
  2256.                         if (j >= nStart && j < nEnd)
  2257.                                 fAverDist += fDist;
  2258.                         else
  2259.                                 fAverDist -= fDist;
  2260.                 }
  2261.  
  2262.                 if (fAverDist < fMinAverDist)
  2263.                 {
  2264.                         p0 = i;
  2265.                         fMinAverDist = fAverDist;
  2266.                 }
  2267.         }
  2268.  
  2269.         return p0;
  2270. }
  2271.  
  2272. void CSvoEnv::CheckUpdateMeshPools()
  2273. {
  2274.         #ifdef FEATURE_SVO_GI_ALLOW_HQ
  2275.         {
  2276.                 PodArrayRT<Vec4>& rAr = gSvoEnv->m_arrRTPoolTris;
  2277.  
  2278.                 AUTO_READLOCK(rAr.m_Lock);
  2279.  
  2280.                 if (rAr.m_bModified)
  2281.                 {
  2282.                         gEnv->pRenderer->RemoveTexture(rAr.m_nTexId);
  2283.                         rAr.m_nTexId = 0;
  2284.  
  2285.                         rAr.m_nTexId = gEnv->pRenderer->DownLoadToVideoMemory3D((byte*)rAr.GetElements(),
  2286.                                                                                 CVoxelSegment::nVoxTexPoolDimXY, CVoxelSegment::nVoxTexPoolDimXY, CVoxelSegment::nVoxTexPoolDimZ, eTF_R32G32B32A32F, eTF_R32G32B32A32F, 1, false, FILTER_POINT, rAr.m_nTexId, 0, FT_DONT_STREAM);
  2287.  
  2288.                         rAr.m_bModified = 0;
  2289.                 }
  2290.         }
  2291.  
  2292.         {
  2293.                 PodArrayRT<ColorB>& rAr = gSvoEnv->m_arrRTPoolTexs;
  2294.  
  2295.                 AUTO_READLOCK(rAr.m_Lock);
  2296.  
  2297.                 if (rAr.m_bModified)
  2298.                 {
  2299.                         gEnv->pRenderer->RemoveTexture(rAr.m_nTexId);
  2300.                         rAr.m_nTexId = 0;
  2301.  
  2302.                         rAr.m_nTexId = gEnv->pRenderer->DownLoadToVideoMemory3D((byte*)rAr.GetElements(),
  2303.                                                                                 CVoxelSegment::nVoxTexPoolDimXY, CVoxelSegment::nVoxTexPoolDimXY, CVoxelSegment::nVoxTexPoolDimZ, m_nVoxTexFormat, m_nVoxTexFormat, 1, false, FILTER_POINT, rAr.m_nTexId, 0, FT_DONT_STREAM);
  2304.  
  2305.                         rAr.m_bModified = 0;
  2306.                 }
  2307.         }
  2308.  
  2309.         {
  2310.                 PodArrayRT<ColorB>& rAr = gSvoEnv->m_arrRTPoolInds;
  2311.  
  2312.                 AUTO_READLOCK(rAr.m_Lock);
  2313.  
  2314.                 if (rAr.m_bModified)
  2315.                 {
  2316.                         gEnv->pRenderer->RemoveTexture(rAr.m_nTexId);
  2317.                         rAr.m_nTexId = 0;
  2318.  
  2319.                         rAr.m_nTexId = gEnv->pRenderer->DownLoadToVideoMemory3D((byte*)rAr.GetElements(),
  2320.                                                                                 CVoxelSegment::nVoxTexPoolDimXY, CVoxelSegment::nVoxTexPoolDimXY, CVoxelSegment::nVoxTexPoolDimZ, m_nVoxTexFormat, m_nVoxTexFormat, 1, false, FILTER_POINT, rAr.m_nTexId, 0, FT_DONT_STREAM);
  2321.  
  2322.                         rAr.m_bModified = 0;
  2323.                 }
  2324.         }
  2325.         #endif
  2326. }
  2327.  
  2328. bool C3DEngine::GetSvoStaticTextures(I3DEngine::SSvoStaticTexInfo& svoInfo, PodArray<I3DEngine::SLightTI>* pLightsTI_S, PodArray<I3DEngine::SLightTI>* pLightsTI_D)
  2329. {
  2330.         return CSvoManager::GetSvoStaticTextures(svoInfo, pLightsTI_S, pLightsTI_D);
  2331. }
  2332.  
  2333. void C3DEngine::GetSvoBricksForUpdate(PodArray<SSvoNodeInfo>& arrNodeInfo, float fNodeSize, PodArray<SVF_P3F_C4B_T2F>* pVertsOut)
  2334. {
  2335.         CSvoManager::GetSvoBricksForUpdate(arrNodeInfo, fNodeSize, pVertsOut);
  2336. }
  2337.  
  2338. void C3DEngine::LoadTISettings(XmlNodeRef pInputNode)
  2339. {
  2340.         const char* szXmlNodeName = "Total_Illumination_v2";
  2341.  
  2342.         // Total illumination
  2343.         if (GetCVars()->e_svoTI_Active >= 0)
  2344.                 GetCVars()->e_svoTI_Apply = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Active", "0"));
  2345.  
  2346.         GetCVars()->e_svoVoxelPoolResolution = 64;
  2347.         int nVoxelPoolResolution = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "VoxelPoolResolution", "0"));
  2348.         while (GetCVars()->e_svoVoxelPoolResolution < nVoxelPoolResolution)
  2349.                 GetCVars()->e_svoVoxelPoolResolution *= 2;
  2350.  
  2351.         GetCVars()->e_svoTI_VoxelizaionLODRatio = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "VoxelizaionLODRatio", "0"));
  2352.         GetCVars()->e_svoDVR_DistRatio = GetCVars()->e_svoTI_VoxelizaionLODRatio / 2;
  2353.  
  2354.         GetCVars()->e_svoTI_InjectionMultiplier = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "InjectionMultiplier", "0"));
  2355.         GetCVars()->e_svoTI_NumberOfBounces = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "NumberOfBounces", "0"));
  2356.         GetCVars()->e_svoTI_Saturation = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Saturation", "0"));
  2357.         GetCVars()->e_svoTI_PropagationBooster = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "PropagationBooster", "0"));
  2358.         if (gEnv->IsEditor())
  2359.         {
  2360.                 GetCVars()->e_svoTI_UpdateLighting = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "UpdateLighting", "0"));
  2361.                 GetCVars()->e_svoTI_UpdateGeometry = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "UpdateGeometry", "0"));
  2362.         }
  2363.         GetCVars()->e_svoTI_SkyColorMultiplier = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "SkyColorMultiplier", "0"));
  2364.         GetCVars()->e_svoTI_UseLightProbes = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "UseLightProbes", "0"));
  2365.         if (!GetCVars()->e_svoTI_UseLightProbes && GetCVars()->e_svoTI_SkyColorMultiplier >= 0)
  2366.                 GetCVars()->e_svoTI_SkyColorMultiplier = -GetCVars()->e_svoTI_SkyColorMultiplier - .0001f;
  2367.         GetCVars()->e_svoTI_ConeMaxLength = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "ConeMaxLength", "0"));
  2368.  
  2369.         GetCVars()->e_svoTI_DiffuseConeWidth = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "DiffuseConeWidth", "0"));
  2370.         GetCVars()->e_svoTI_DiffuseBias = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "DiffuseBias", "0"));
  2371.         GetCVars()->e_svoTI_DiffuseAmplifier = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "DiffuseAmplifier", "0"));
  2372.         if (GetCVars()->e_svoTI_Diffuse_Cache)
  2373.                 GetCVars()->e_svoTI_NumberOfBounces++;
  2374.  
  2375.         GetCVars()->e_svoTI_SpecularAmplifier = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "SpecularAmplifier", "0"));
  2376.  
  2377.         GetCVars()->e_svoMinNodeSize = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "MinNodeSize", "0"));
  2378.  
  2379.         GetCVars()->e_svoTI_SkipNonGILights = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "SkipNonGILights", "0"));
  2380.         GetCVars()->e_svoTI_ForceGIForAllLights = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "ForceGIForAllLights", "0"));
  2381.         GetCVars()->e_svoTI_SSAOAmount = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "SSAOAmount", "0"));
  2382.         GetCVars()->e_svoTI_PortalsDeform = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "PortalsDeform", "0"));
  2383.         GetCVars()->e_svoTI_PortalsInject = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "PortalsInject", "0"));
  2384.         GetCVars()->e_svoTI_ObjectsMaxViewDistance = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "ObjectsMaxViewDistance", "0"));
  2385.         GetCVars()->e_svoTI_SunRSMInject = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "SunRSMInject", "0"));
  2386.         GetCVars()->e_svoTI_SSDepthTrace = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "SSDepthTrace", "0"));
  2387.  
  2388.         GetCVars()->e_svoTI_Troposphere_Active = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_Active", "0"));
  2389.         GetCVars()->e_svoTI_Troposphere_Brightness = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_Brightness", "0"));
  2390.         GetCVars()->e_svoTI_Troposphere_Ground_Height = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_Ground_Height", "0"));
  2391.         GetCVars()->e_svoTI_Troposphere_Layer0_Height = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_Layer0_Height", "0"));
  2392.         GetCVars()->e_svoTI_Troposphere_Layer1_Height = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_Layer1_Height", "0"));
  2393.         GetCVars()->e_svoTI_Troposphere_Snow_Height = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_Snow_Height", "0"));
  2394.         GetCVars()->e_svoTI_Troposphere_Layer0_Rand = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_Layer0_Rand", "0"));
  2395.         GetCVars()->e_svoTI_Troposphere_Layer1_Rand = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_Layer1_Rand", "0"));
  2396.         GetCVars()->e_svoTI_Troposphere_Layer0_Dens = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_Layer0_Dens", "0"));
  2397.         GetCVars()->e_svoTI_Troposphere_Layer1_Dens = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_Layer1_Dens", "0"));
  2398.         //GetCVars()->e_svoTI_Troposphere_CloudGen_Height = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_CloudGen_Height", "0"));
  2399.         GetCVars()->e_svoTI_Troposphere_CloudGen_Freq = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_CloudGen_Freq", "0"));
  2400.         GetCVars()->e_svoTI_Troposphere_CloudGen_FreqStep = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_CloudGen_FreqStep", "0"));
  2401.         GetCVars()->e_svoTI_Troposphere_CloudGen_Scale = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_CloudGen_Scale", "0"));
  2402.         GetCVars()->e_svoTI_Troposphere_CloudGenTurb_Freq = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_CloudGenTurb_Freq", "0"));
  2403.         GetCVars()->e_svoTI_Troposphere_CloudGenTurb_Scale = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_CloudGenTurb_Scale", "0"));
  2404.         GetCVars()->e_svoTI_Troposphere_Density = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_Density", "0"));
  2405.         //if (GetCVars()->e_svoTI_Troposphere_Subdivide >= 0)
  2406.         //GetCVars()->e_svoTI_Troposphere_Subdivide = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "Troposphere_Subdivide", "0"));
  2407.         GetCVars()->e_svoTI_Troposphere_Subdivide = GetCVars()->e_svoTI_Troposphere_Active;
  2408.  
  2409.         GetCVars()->e_svoTI_AnalyticalOccluders = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "AnalyticalOccluders", "0"));
  2410.         GetCVars()->e_svoTI_AnalyticalGI = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "AnalyticalGI", "0"));
  2411.         GetCVars()->e_svoTI_TraceVoxels = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "TraceVoxels", "1"));
  2412.  
  2413.         int nLowSpecMode = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "LowSpecMode", "0"));
  2414.         if (nLowSpecMode > -2 && gEnv->IsEditor()) // otherwise we use value from sys_spec_Light.cfg
  2415.                 GetCVars()->e_svoTI_LowSpecMode = nLowSpecMode;
  2416.  
  2417.         GetCVars()->e_svoTI_HalfresKernelPrimary = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "HalfresKernelPrimary", "0"));
  2418.         GetCVars()->e_svoTI_HalfresKernelSecondary = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "HalfresKernelSecondary", "0"));
  2419.         GetCVars()->e_svoTI_UseTODSkyColor = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "UseTODSkyColor", "0"));
  2420.  
  2421.         GetCVars()->e_svoTI_HighGlossOcclusion = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "HighGlossOcclusion", "0"));
  2422.         GetCVars()->e_svoTI_TranslucentBrightness = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "TranslucentBrightness", "2.5"));
  2423.  
  2424.         #ifdef FEATURE_SVO_GI_ALLOW_HQ
  2425.         GetCVars()->e_svoTI_IntegrationMode = (int)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "IntegrationMode", "0"));
  2426.         #else
  2427.         GetCVars()->e_svoTI_IntegrationMode = 0;
  2428.         #endif
  2429.  
  2430.         GetCVars()->e_svoTI_RT_MaxDist = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "RT_MaxDist", "0"));
  2431.  
  2432.         GetCVars()->e_svoTI_ConstantAmbientDebug = (float)atof(GetXMLAttribText(pInputNode, szXmlNodeName, "ConstantAmbientDebug", "0"));
  2433.  
  2434.         if (GetCVars()->e_svoTI_IntegrationMode < 1) // AO
  2435.         {
  2436.                 GetCVars()->e_svoTI_NumberOfBounces = min(GetCVars()->e_svoTI_NumberOfBounces, 1);
  2437.         }
  2438.  
  2439.         if (GetCVars()->e_svoTI_ConstantAmbientDebug)
  2440.         {
  2441.                 GetCVars()->e_svoTI_DiffuseAmplifier = 0;
  2442.                 GetCVars()->e_svoTI_DiffuseBias = GetCVars()->e_svoTI_ConstantAmbientDebug;
  2443.                 GetCVars()->e_svoTI_SpecularAmplifier = 0;
  2444.         }
  2445.  
  2446.         // validate MinNodeSize
  2447.         float fSize = (float)Get3DEngine()->GetTerrainSize();
  2448.         for (; fSize > 0.01f && fSize >= GetCVars()->e_svoMinNodeSize * 2.f; fSize /= 2.f)
  2449.               &