BVB Source Codes

CRYENGINE Show terrain_node.cpp Source code

Return Download CRYENGINE: download terrain_node.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:   terrain_node.cpp
  5. //  Version:     v1.00
  6. //  Created:     28/5/2001 by Vladimir Kajalin
  7. //  Compilers:   Visual Studio.NET
  8. //  Description: terrain node
  9. // -------------------------------------------------------------------------
  10. //  History:
  11. //
  12. ////////////////////////////////////////////////////////////////////////////
  13.  
  14. #include "StdAfx.h"
  15. #include "terrain_sector.h"
  16. #include "terrain.h"
  17. #include "ObjMan.h"
  18. #include "VisAreas.h"
  19. #include "Vegetation.h"
  20. #include <CryMath/AABBSV.h>
  21. #include "LightEntity.h"
  22. #include <CryMath/MTPseudoRandom.h>
  23.  
  24. CProcVegetPoolMan* CTerrainNode::m_pProcObjPoolMan = NULL;
  25. SProcObjChunkPool* CTerrainNode::m_pProcObjChunkPool = NULL;
  26. int CTerrainNode::m_nNodesCounter = 0;
  27.  
  28. CTerrainNode* CTerrainNode::GetTexuringSourceNode(int nTexMML, eTexureType eTexType)
  29. {
  30.         CTerrainNode* pTexSourceNode = this;
  31.         while (pTexSourceNode->m_pParent)
  32.         {
  33.                 if (eTexType == ett_Diffuse)
  34.                 {
  35.                         if (pTexSourceNode->m_nTreeLevel < nTexMML || pTexSourceNode->m_nNodeTextureOffset < 0)
  36.                                 pTexSourceNode = pTexSourceNode->m_pParent;
  37.                         else
  38.                                 break;
  39.                 }
  40.                 else if (eTexType == ett_LM)
  41.                 {
  42.                         if (pTexSourceNode->m_nTreeLevel < nTexMML || pTexSourceNode->m_nNodeTextureOffset < 0 /*|| pTexSourceNode->GetSectorSizeInHeightmapUnits()<TERRAIN_LM_TEX_RES*/)
  43.                                 pTexSourceNode = pTexSourceNode->m_pParent;
  44.                         else
  45.                                 break;
  46.                 }
  47.                 else
  48.                         assert(0);
  49.  
  50.                 assert(pTexSourceNode);
  51.         }
  52.  
  53.         return pTexSourceNode;
  54. }
  55.  
  56. CTerrainNode* CTerrainNode::GetReadyTexSourceNode(int nTexMML, eTexureType eTexType)
  57. {
  58.         Vec3 vSunDir = Get3DEngine()->GetSunDir().normalized();
  59.  
  60.         CTerrainNode* pTexSourceNode = this;
  61.         while (pTexSourceNode)
  62.         {
  63.                 if (eTexType == ett_Diffuse)
  64.                 {
  65.                         if (pTexSourceNode->m_nTreeLevel < nTexMML || !pTexSourceNode->m_nNodeTexSet.nTex0)
  66.                                 pTexSourceNode = pTexSourceNode->m_pParent;
  67.                         else
  68.                                 break;
  69.                 }
  70.                 else if (eTexType == ett_LM)
  71.                 {
  72.                         if (pTexSourceNode->m_nTreeLevel < nTexMML || !pTexSourceNode->m_nNodeTexSet.nTex1)
  73.                                 pTexSourceNode = pTexSourceNode->m_pParent;
  74.                         else
  75.                                 break;
  76.                 }
  77.         }
  78.  
  79.         return pTexSourceNode;
  80. }
  81.  
  82. void CTerrainNode::RequestTextures(const SRenderingPassInfo& passInfo)
  83. {
  84.         FUNCTION_PROFILER_3DENGINE;
  85.  
  86.         if (passInfo.IsRecursivePass())
  87.                 return;
  88.  
  89.         // check if diffuse need to be updated
  90.         if (CTerrainNode* pCorrectDiffSourceNode = GetTexuringSourceNode(m_cNodeNewTexMML, ett_Diffuse))
  91.         {
  92.                 //    if(       pCorrectDiffSourceNode != pDiffSourceNode )
  93.                 {
  94.                         while (pCorrectDiffSourceNode)
  95.                         {
  96.                                 GetTerrain()->ActivateNodeTexture(pCorrectDiffSourceNode, passInfo);
  97.                                 pCorrectDiffSourceNode = pCorrectDiffSourceNode->m_pParent;
  98.                         }
  99.                 }
  100.         }
  101.  
  102.         // check if lightmap need to be updated
  103.         if (CTerrainNode* pCorrectLMapSourceNode = GetTexuringSourceNode(m_cNodeNewTexMML, ett_LM))
  104.         {
  105.                 //    if(       pCorrectLMapSourceNode != pLMSourceNode )
  106.                 {
  107.                         while (pCorrectLMapSourceNode)
  108.                         {
  109.                                 GetTerrain()->ActivateNodeTexture(pCorrectLMapSourceNode, passInfo);
  110.                                 pCorrectLMapSourceNode = pCorrectLMapSourceNode->m_pParent;
  111.                         }
  112.                 }
  113.         }
  114. }
  115.  
  116. // setup texture id and texgen parameters
  117. void CTerrainNode::SetupTexturing(bool bMakeUncompressedForEditing, const SRenderingPassInfo& passInfo)
  118. {
  119.         FUNCTION_PROFILER_3DENGINE;
  120.  
  121. #ifndef _RELEASE
  122.         if (gEnv->IsEditor())
  123.         {
  124.                 if (CTerrainNode* pTextureSourceNode = GetReadyTexSourceNode(passInfo.IsShadowPass() ? 0 : m_cNodeNewTexMML, ett_Diffuse))
  125.                 {
  126.                         // update RGB and normal textures
  127.                         if (pTextureSourceNode->m_eTextureEditingState == eTES_SectorIsModified_AtlasIsDirty && C3DEngine::m_pGetLayerIdAtCallback)
  128.                         {
  129.                                 pTextureSourceNode->UpdateNodeTextureFromEditorData();
  130.                                 pTextureSourceNode->m_eTextureEditingState = eTES_SectorIsModified_AtlasIsUpToDate;
  131.                         }
  132.  
  133.                         // update elevation texture
  134.                         if (pTextureSourceNode->m_eElevTexEditingState == eTES_SectorIsModified_AtlasIsDirty)
  135.                         {
  136.                                 pTextureSourceNode->UpdateNodeNormalMapFromEditorData();
  137.  
  138.                                 static Array2d<float> arrHmData;
  139.                                 pTextureSourceNode->FillSectorHeightMapTextureData(arrHmData);
  140.                                 m_pTerrain->m_texCache[2].UpdateTexture((byte*)arrHmData.GetData(), pTextureSourceNode->m_nNodeTexSet.nSlot0);
  141.  
  142.                                 pTextureSourceNode->m_eElevTexEditingState = eTES_SectorIsModified_AtlasIsUpToDate;
  143.                         }
  144.                 }
  145.         }
  146. #endif // _RELEASE
  147.  
  148.         CheckLeafData();
  149.  
  150.         // find parent node containing requested texture lod
  151.         CTerrainNode* pTextureSourceNode = GetReadyTexSourceNode(passInfo.IsShadowPass() ? 0 : m_cNodeNewTexMML, ett_Diffuse);
  152.  
  153.         if (!pTextureSourceNode) // at least root texture has to be loaded
  154.                 pTextureSourceNode = m_pTerrain->GetParentNode(m_nSID);
  155.  
  156.         int nRL = passInfo.GetRecursiveLevel();
  157.  
  158.         float fPrevTexGenScale = GetLeafData()->m_arrTexGen[nRL][2];
  159.  
  160.         if (pTextureSourceNode)
  161.         {
  162.                 // set texture generation parameters for terrain diffuse map
  163.  
  164.                 if (gEnv->IsEditor())
  165.                 {
  166.                         CalculateTexGen(pTextureSourceNode, GetLeafData()->m_arrTexGen[nRL][0], GetLeafData()->m_arrTexGen[nRL][1], GetLeafData()->m_arrTexGen[nRL][2]);
  167.  
  168.                         pTextureSourceNode->m_nNodeTexSet.fTexOffsetX = GetLeafData()->m_arrTexGen[nRL][0];
  169.                         pTextureSourceNode->m_nNodeTexSet.fTexOffsetY = GetLeafData()->m_arrTexGen[nRL][1];
  170.                         pTextureSourceNode->m_nNodeTexSet.fTexScale = GetLeafData()->m_arrTexGen[nRL][2];
  171.                 }
  172.                 else
  173.                 {
  174.                         GetLeafData()->m_arrTexGen[nRL][0] = pTextureSourceNode->m_nNodeTexSet.fTexOffsetX;
  175.                         GetLeafData()->m_arrTexGen[nRL][1] = pTextureSourceNode->m_nNodeTexSet.fTexOffsetY;
  176.                         GetLeafData()->m_arrTexGen[nRL][2] = pTextureSourceNode->m_nNodeTexSet.fTexScale;
  177.                 }
  178.  
  179.                 GetLeafData()->m_arrTexGen[nRL][3] = gEnv->p3DEngine->GetTerrainTextureMultiplier(m_nSID);
  180.         }
  181.  
  182.         // set output texture id's
  183.         int nDefaultTexId = Get3DEngine()->m_pSegmentsManager ? GetTerrain()->m_nBlackTexId : GetTerrain()->m_nWhiteTexId;
  184.  
  185.         m_nTexSet.nTex0 = (pTextureSourceNode && pTextureSourceNode->m_nNodeTexSet.nTex0) ?
  186.                           pTextureSourceNode->m_nNodeTexSet.nTex0 : nDefaultTexId;
  187.  
  188.         m_nTexSet.nTex1 = (pTextureSourceNode && pTextureSourceNode->m_nNodeTexSet.nTex1) ?
  189.                           pTextureSourceNode->m_nNodeTexSet.nTex1 : nDefaultTexId;
  190.  
  191.         m_nTexSet.nTex2 = (pTextureSourceNode && pTextureSourceNode->m_nNodeTexSet.nTex2) ?
  192.                                                                                 pTextureSourceNode->m_nNodeTexSet.nTex2 : nDefaultTexId;
  193.  
  194.         if (pTextureSourceNode && pTextureSourceNode->m_nNodeTexSet.nTex0)
  195.                 m_nTexSet = pTextureSourceNode->m_nNodeTexSet;
  196.  
  197.         if (fPrevTexGenScale != GetLeafData()->m_arrTexGen[nRL][2])
  198.                 InvalidatePermanentRenderObject();
  199. }
  200.  
  201. float GetPointToBoxDistance(Vec3 vPos, AABB bbox)
  202. {
  203.         if (vPos.x >= bbox.min.x && vPos.x <= bbox.max.x)
  204.                 if (vPos.y >= bbox.min.y && vPos.y <= bbox.max.y)
  205.                         if (vPos.z >= bbox.min.z && vPos.z <= bbox.max.z)
  206.                                 return 0;
  207.         // inside
  208.  
  209.         float dy;
  210.         if (vPos.y < bbox.min.y)
  211.                 dy = bbox.min.y - vPos.y;
  212.         else if (vPos.y > bbox.max.y)
  213.                 dy = vPos.y - bbox.max.y;
  214.         else
  215.                 dy = 0;
  216.  
  217.         float dx;
  218.         if (vPos.x < bbox.min.x)
  219.                 dx = bbox.min.x - vPos.x;
  220.         else if (vPos.x > bbox.max.x)
  221.                 dx = vPos.x - bbox.max.x;
  222.         else
  223.                 dx = 0;
  224.  
  225.         float dz;
  226.         if (vPos.z < bbox.min.z)
  227.                 dz = bbox.min.z - vPos.z;
  228.         else if (vPos.z > bbox.max.z)
  229.                 dz = vPos.z - bbox.max.z;
  230.         else
  231.                 dz = 0;
  232.  
  233.         return sqrt_tpl(dx * dx + dy * dy + dz * dz);
  234. }
  235.  
  236. // Hierarchically check nodes visibility
  237. // Add visible sectors to the list of visible terrain sectors
  238.  
  239. bool CTerrainNode::CheckVis(bool bAllInside, bool bAllowRenderIntoCBuffer, const Vec3& vSegmentOrigin, const SRenderingPassInfo& passInfo)
  240. {
  241.         FUNCTION_PROFILER_3DENGINE;
  242.  
  243.         m_cNewGeomMML = MML_NOT_SET;
  244.  
  245.         const AABB& boxWS = GetBBox();
  246.         const CCamera& rCamera = passInfo.GetCamera();
  247.  
  248.         if (!bAllInside && !rCamera.IsAABBVisible_EHM(boxWS, &bAllInside))
  249.                 return false;
  250.  
  251.         // get distances
  252.         m_arrfDistance[passInfo.GetRecursiveLevel()] = GetPointToBoxDistance(rCamera.GetPosition(), boxWS);
  253.  
  254.         if (m_arrfDistance[passInfo.GetRecursiveLevel()] > rCamera.GetFarPlane())
  255.                 return false; // too far
  256.  
  257.         if (m_bHasHoles == 2)
  258.                 return false; // has no visible mesh
  259.  
  260.         // occlusion test (affects only static objects)
  261.         if (m_pParent && GetObjManager()->IsBoxOccluded(boxWS, m_arrfDistance[passInfo.GetRecursiveLevel()], &m_occlusionTestClient, false, eoot_TERRAIN_NODE, passInfo))
  262.                 return false;
  263.  
  264.         // find LOD of this sector
  265.         SetLOD(passInfo);
  266.  
  267.         m_nSetLodFrameId = passInfo.GetMainFrameID();
  268.  
  269.         int nSectorSize = CTerrain::GetSectorSize() << m_nTreeLevel;
  270.  
  271.         bool bContinueRecursion = false;
  272.         if (m_pChilds &&
  273.             (m_arrfDistance[passInfo.GetRecursiveLevel()] < GetCVars()->e_TerrainLodDistRatio * (float)nSectorSize ||
  274.              (m_cNewGeomMML + GetTerrain()->m_nBitShift - 1) < m_nTreeLevel ||
  275.              (m_cNodeNewTexMML + GetTerrain()->m_nBitShift - 1) < m_nTreeLevel ||
  276.              m_bMergeNotAllowed))
  277.                 bContinueRecursion = true;
  278.  
  279.         if (bContinueRecursion)
  280.         {
  281.                 Vec3 vCenter = boxWS.GetCenter();
  282.  
  283.                 Vec3 vCamPos = rCamera.GetPosition();
  284.  
  285.                 int nFirst =
  286.                   ((vCamPos.x > vCenter.x) ? 2 : 0) |
  287.                   ((vCamPos.y > vCenter.y) ? 1 : 0);
  288.  
  289.                 m_pChilds[nFirst].CheckVis(bAllInside, bAllowRenderIntoCBuffer, vSegmentOrigin, passInfo);
  290.                 m_pChilds[nFirst ^ 1].CheckVis(bAllInside, bAllowRenderIntoCBuffer, vSegmentOrigin, passInfo);
  291.                 m_pChilds[nFirst ^ 2].CheckVis(bAllInside, bAllowRenderIntoCBuffer, vSegmentOrigin, passInfo);
  292.                 m_pChilds[nFirst ^ 3].CheckVis(bAllInside, bAllowRenderIntoCBuffer, vSegmentOrigin, passInfo);
  293.         }
  294.         else
  295.         {
  296.                 if (GetCVars()->e_StatObjBufferRenderTasks == 1 && passInfo.IsGeneralPass() && JobManager::InvokeAsJob("CheckOcclusion"))
  297.                 {
  298.                         GetObjManager()->PushIntoCullQueue(SCheckOcclusionJobData::CreateTerrainJobData(this, GetBBox(), m_arrfDistance[passInfo.GetRecursiveLevel()]));
  299.                 }
  300.                 else
  301.                         GetTerrain()->AddVisSector(this);
  302.  
  303.                 if (boxWS.min.z < GetTerrain()->GetWaterLevel() && passInfo.IsGeneralPass())
  304.                         if (m_arrfDistance[passInfo.GetRecursiveLevel()] < GetTerrain()->m_fDistanceToSectorWithWater)
  305.                                 GetTerrain()->m_fDistanceToSectorWithWater = m_arrfDistance[passInfo.GetRecursiveLevel()];
  306.  
  307.                 if (m_pChilds)
  308.                         for (int i = 0; i < 4; i++)
  309.                                 m_pChilds[i].SetChildsLod(m_cNewGeomMML, passInfo);
  310.  
  311.                 RequestTextures(passInfo);
  312.         }
  313.  
  314.         // update procedural vegetation
  315.         IF (passInfo.IsGeneralPass() && GetTerrain()->m_bProcVegetationInUse && GetCVars()->e_ProcVegetation, 0)
  316.         {
  317.                 CTerrainNode* pNode = this;
  318.  
  319.                 while (pNode && pNode->m_nTreeLevel < GetCVars()->e_ProcVegetationMaxCacheLevels)
  320.                 {
  321.                         if (pNode->m_arrfDistance[passInfo.GetRecursiveLevel()] < GetCVars()->e_ProcVegetationMaxViewDistance * (pNode->GetBBox().GetSize().x / 64.f))
  322.                                 GetTerrain()->ActivateNodeProcObj(pNode);
  323.  
  324.                         pNode = pNode->m_pParent;
  325.                 }
  326.         }
  327.  
  328.         return true;
  329. }
  330.  
  331. void CTerrainNode::Init(int x1, int y1, int nNodeSize, CTerrainNode* pParent, bool bBuildErrorsTable, int nSID)
  332. {
  333.         m_nSID = nSID;
  334.         m_pChilds = NULL;
  335.         const int numGeomErrors = GetTerrain()->m_nUnitsToSectorBitShift;
  336.         m_pGeomErrors = new float[numGeomErrors]; // TODO: fix duplicated reallocation
  337.         memset(m_pGeomErrors, 0, sizeof(float) * GetTerrain()->m_nUnitsToSectorBitShift);
  338.  
  339.         m_pProcObjPoolPtr = NULL;
  340.  
  341.         //      ZeroStruct(m_arrChilds);
  342.  
  343.         m_pReadStream = NULL;
  344.         m_eTexStreamingStatus = ecss_NotLoaded;
  345.  
  346.         // flags
  347.         m_bNoOcclusion = 0;
  348.         m_bProcObjectsReady = 0;
  349.         m_bMergeNotAllowed = 0;
  350.         m_bHasHoles = 0;
  351.  
  352. #ifndef _RELEASE
  353.         m_eTextureEditingState = m_eElevTexEditingState = eTES_SectorIsUnmodified;
  354. #endif // _RELEASE
  355.  
  356.         m_nOriginX = m_nOriginY = 0; // sector origin
  357.         m_nLastTimeUsed = 0;         // basically last time rendered
  358.  
  359.         uint8 m_cNewGeomMML = m_cCurrGeomMML = m_cNewGeomMML_Min = m_cNewGeomMML_Max = m_cNodeNewTexMML = m_cNodeNewTexMML_Min = 0;
  360.  
  361.         m_pLeafData = 0;
  362.  
  363.         m_nTreeLevel = 0;
  364.  
  365.         ZeroStruct(m_nNodeTexSet);
  366.         ZeroStruct(m_nTexSet);
  367.  
  368.         //m_nNodeRenderLastFrameId=0;
  369.         m_nNodeTextureLastUsedSec4 = (~0);
  370.         m_boxHeigtmapLocal.Reset();
  371.         m_pParent = NULL;
  372.         //m_nSetupTexGensFrameId=0;
  373.  
  374.         m_cNewGeomMML = 100;
  375.         m_nLastTimeUsed = (int)GetCurTimeSec() + 20;
  376.  
  377.         m_cNodeNewTexMML = 100;
  378.         m_pParent = NULL;
  379.  
  380.         m_pParent = pParent;
  381.  
  382.         m_nOriginX = x1;
  383.         m_nOriginY = y1;
  384.  
  385.         m_rangeInfo.fOffset = 0;
  386.         m_rangeInfo.fRange = 0;
  387.         m_rangeInfo.nSize = 0;
  388.         m_rangeInfo.pHMData = NULL;
  389.         m_rangeInfo.pSTPalette = NULL;
  390.  
  391.         for (int iStackLevel = 0; iStackLevel < MAX_RECURSION_LEVELS; iStackLevel++)
  392.         {
  393.                 m_arrfDistance[iStackLevel] = 0.f;
  394.         }
  395.  
  396.         if (nNodeSize == CTerrain::GetSectorSize())
  397.         {
  398.                 //              memset(m_arrChilds,0,sizeof(m_arrChilds));
  399.                 m_nTreeLevel = 0;
  400.                 /*              InitSectorBoundsAndErrorLevels(bBuildErrorsTable);
  401.  
  402.                     static int tic=0;
  403.                     if((tic&511)==0)
  404.                     {
  405.                       PrintMessagePlus(".");                                                            // to visualize progress
  406.                       PrintMessage("");
  407.                     }
  408.                     tic++;
  409.                  */
  410.         }
  411.         else
  412.         {
  413.                 int nSize = nNodeSize / 2;
  414.                 m_pChilds = new CTerrainNode[4];
  415.                 m_pChilds[0].Init(x1, y1, nSize, this, bBuildErrorsTable, m_nSID);
  416.                 m_pChilds[1].Init(x1 + nSize, y1, nSize, this, bBuildErrorsTable, m_nSID);
  417.                 m_pChilds[2].Init(x1, y1 + nSize, nSize, this, bBuildErrorsTable, m_nSID);
  418.                 m_pChilds[3].Init(x1 + nSize, y1 + nSize, nSize, this, bBuildErrorsTable, m_nSID);
  419.                 m_nTreeLevel = m_pChilds[0].m_nTreeLevel + 1;
  420.  
  421.                 for (int i = 0; i < numGeomErrors; i++)
  422.                 {
  423.                         m_pGeomErrors[i] = max(max(
  424.                                                  m_pChilds[0].m_pGeomErrors[i],
  425.                                                  m_pChilds[1].m_pGeomErrors[i]), max(
  426.                                                  m_pChilds[2].m_pGeomErrors[i],
  427.                                                  m_pChilds[3].m_pGeomErrors[i]));
  428.                 }
  429.  
  430.                 m_boxHeigtmapLocal.min = SetMaxBB();
  431.                 m_boxHeigtmapLocal.max = SetMinBB();
  432.  
  433.                 for (int nChild = 0; nChild < 4; nChild++)
  434.                 {
  435.                         m_boxHeigtmapLocal.min.CheckMin(m_pChilds[nChild].m_boxHeigtmapLocal.min);
  436.                         m_boxHeigtmapLocal.max.CheckMax(m_pChilds[nChild].m_boxHeigtmapLocal.max);
  437.                 }
  438.  
  439.                 m_arrfDistance[0] = 2.f * CTerrain::GetTerrainSize();
  440.                 if (m_arrfDistance[0] < 0)
  441.                         m_arrfDistance[0] = 0;
  442.  
  443.                 m_nLastTimeUsed = ~0;//GetCurTimeSec() + 100;
  444.         }
  445.  
  446.         int nSectorSize = CTerrain::GetSectorSize() << m_nTreeLevel;
  447.         assert(x1 >= 0 && y1 >= 0 && x1 < CTerrain::GetTerrainSize() && y1 < CTerrain::GetTerrainSize());
  448.         GetTerrain()->m_arrSecInfoPyramid[nSID][m_nTreeLevel][x1 / nSectorSize][y1 / nSectorSize] = this;
  449.  
  450.         //      m_boxStatics = m_boxHeigtmap;
  451. }
  452.  
  453. CTerrainNode::~CTerrainNode()
  454. {
  455.         if (GetTerrain()->m_pTerrainUpdateDispatcher)
  456.                 GetTerrain()->m_pTerrainUpdateDispatcher->RemoveJob(this);
  457.  
  458.         Get3DEngine()->OnCasterDeleted(this);
  459.         if (GetRenderer())
  460.         {
  461.                 if (ShadowFrustumMGPUCache* pFrustumCache = GetRenderer()->GetShadowFrustumMGPUCache())
  462.                         pFrustumCache->DeleteFromCache(this);
  463.         }
  464.  
  465.         ReleaseHeightMapGeometry();
  466.  
  467.         UnloadNodeTexture(false);
  468.  
  469.         SAFE_DELETE_ARRAY(m_pChilds);
  470.  
  471.         RemoveProcObjects(false);
  472.  
  473.         m_bHasHoles = 0;
  474.  
  475.         delete m_pLeafData;
  476.         m_pLeafData = NULL;
  477.  
  478.         delete[] m_rangeInfo.pHMData;
  479.         m_rangeInfo.pHMData = NULL;
  480.  
  481.         delete[] m_rangeInfo.pSTPalette;
  482.         m_rangeInfo.pSTPalette = NULL;
  483.  
  484.         delete[] m_pGeomErrors;
  485.         m_pGeomErrors = NULL;
  486.  
  487.         int nSectorSize = CTerrain::GetSectorSize() << m_nTreeLevel;
  488.         assert(m_nOriginX < CTerrain::GetTerrainSize() && m_nOriginY < CTerrain::GetTerrainSize());
  489.         GetTerrain()->m_arrSecInfoPyramid[m_nSID][m_nTreeLevel][m_nOriginX / nSectorSize][m_nOriginY / nSectorSize] = NULL;
  490.  
  491.         m_nNodesCounter--;
  492. }
  493.  
  494. void CTerrainNode::CheckLeafData()
  495. {
  496.         if (!m_pLeafData)
  497.                 m_pLeafData = new STerrainNodeLeafData;
  498. }
  499.  
  500. PodArray<byte> gTerrainCompressedImgData;
  501.  
  502. void CTerrainNode::SaveCompressedMipmapLevel(const void* data, size_t size, void* userData)
  503. {
  504.         gTerrainCompressedImgData.Clear();
  505.         gTerrainCompressedImgData.AddList((byte*)data, size);
  506. }
  507.  
  508. void CTerrainNode::EnableTextureEditingMode(unsigned int nEditorDiffuseTex)
  509. {
  510.         FUNCTION_PROFILER_3DENGINE;
  511.  
  512. #ifdef SEG_WORLD
  513.         if (nEditorDiffuseTex == (unsigned int)-1)
  514.                 return;
  515. #endif
  516.  
  517. #ifndef _RELEASE
  518.         if (nEditorDiffuseTex > 0)
  519.                 m_eTextureEditingState = eTES_SectorIsModified_AtlasIsDirty;
  520. #endif // _RELEASE
  521. }
  522.  
  523. void CTerrainNode::UpdateNodeTextureFromEditorData()
  524. {
  525.         FUNCTION_PROFILER_3DENGINE;
  526.  
  527.         int nTexSize = GetTerrain()->m_arrBaseTexInfos[0].m_TerrainTextureLayer[0].nSectorSizePixels;
  528.         ETEX_Format texFormat = GetTerrain()->m_arrBaseTexInfos[0].m_TerrainTextureLayer[0].eTexFormat;
  529.  
  530.         static Array2d<ColorB> arrRGB;
  531.         arrRGB.Allocate(nTexSize);
  532.  
  533.         float fMult = 1.f / gEnv->p3DEngine->GetTerrainTextureMultiplier(0);
  534.  
  535.         float fBoxSize = GetBBox().GetSize().x;
  536.  
  537.         for (int x = 0; x < nTexSize; x++)
  538.         {
  539.                 for (int y = 0; y < nTexSize; y++)
  540.                 {
  541.                         arrRGB[x][y] = C3DEngine::m_pGetLayerIdAtCallback->GetColorAtPosition(
  542.                                 (float)m_nOriginY + fBoxSize * float(y) / nTexSize * (1.f + 1.f / (float)nTexSize),
  543.                                 (float)m_nOriginX + fBoxSize * float(x) / nTexSize * (1.f + 1.f / (float)nTexSize),
  544.                                 true);
  545.  
  546.                         ColorF colRGB;
  547.                         colRGB.r = 1.f / 255.f * arrRGB[x][y].r;
  548.                         colRGB.g = 1.f / 255.f * arrRGB[x][y].g;
  549.                         colRGB.b = 1.f / 255.f * arrRGB[x][y].b;
  550.                         colRGB.a = 1.f;
  551.  
  552.                         {
  553.                                 // Convert to linear space
  554.                                 colRGB.srgb2rgb();
  555.  
  556.                                 colRGB *= fMult;
  557.                                 colRGB.Clamp();
  558.  
  559.                                 // Convert to gamma 2.2 space
  560.                                 colRGB.rgb2srgb();
  561.  
  562.                                 arrRGB[x][y].r = (uint32)(colRGB.r * 255.0f + 0.5f);
  563.                                 arrRGB[x][y].g = (uint32)(colRGB.g * 255.0f + 0.5f);
  564.                                 arrRGB[x][y].b = (uint32)(colRGB.b * 255.0f + 0.5f);
  565.                                 arrRGB[x][y].a = 255;
  566.                         }
  567.                 }
  568.         }
  569.  
  570.         GetRenderer()->DXTCompress((byte*)arrRGB.GetData(), nTexSize, nTexSize, texFormat, false, false, 4, SaveCompressedMipmapLevel);
  571.  
  572.         m_pTerrain->m_texCache[0].UpdateTexture(gTerrainCompressedImgData.GetElements(), m_nNodeTexSet.nSlot0);
  573. }
  574.  
  575. void CTerrainNode::UpdateNodeNormalMapFromEditorData()
  576. {
  577.         FUNCTION_PROFILER_3DENGINE;
  578.  
  579.         int nTexSize = GetTerrain()->m_arrBaseTexInfos[0].m_TerrainTextureLayer[1].nSectorSizePixels;
  580.         ETEX_Format texFormat = GetTerrain()->m_arrBaseTexInfos[0].m_TerrainTextureLayer[1].eTexFormat;
  581.  
  582.         static Array2d<ColorB> arrRGB;
  583.         arrRGB.Allocate(nTexSize);
  584.  
  585.         float fBoxSize = GetBBox().GetSize().x;
  586.  
  587.         for (int x = 0; x < nTexSize; x++)
  588.         {
  589.                 for (int y = 0; y < nTexSize; y++)
  590.                 {
  591.                         Vec3 vWSPos(
  592.                                 (float)m_nOriginX + fBoxSize * float(x) / nTexSize * (1.f + 1.f / (float)nTexSize),
  593.                                 (float)m_nOriginY + fBoxSize * float(y) / nTexSize * (1.f + 1.f / (float)nTexSize), 0);
  594.  
  595.                         Vec3 vNormal = GetTerrain()->GetTerrainSurfaceNormal_Int((int)vWSPos.x, (int)vWSPos.y, 0);
  596.  
  597.                         uint32 dwR = SATURATEB(uint32(vNormal.x * 127.5f + 127.5f));
  598.                         uint32 dwB = SATURATEB(uint32(vNormal.y * 127.5f + 127.5f));
  599.                         uint32 dwA = 0;
  600.                         uint32 dwG = 0;
  601.  
  602.                         arrRGB[x][y] = (dwA << 24) | (dwB << 16) | (dwG << 8) | (dwR);
  603.                 }
  604.         }
  605.  
  606.         GetRenderer()->DXTCompress((byte*)arrRGB.GetData(), nTexSize, nTexSize, texFormat, false, false, 4, SaveCompressedMipmapLevel);
  607.  
  608.         m_pTerrain->m_texCache[1].UpdateTexture(gTerrainCompressedImgData.GetElements(), m_nNodeTexSet.nSlot1);
  609. }
  610.  
  611. void CTerrainNode::CheckNodeGeomUnload(const SRenderingPassInfo& passInfo)
  612. {
  613.         FUNCTION_PROFILER_3DENGINE;
  614.  
  615.         float fDistanse = GetPointToBoxDistance(passInfo.GetCamera().GetPosition(), GetBBox()) * passInfo.GetZoomFactor();
  616.  
  617.         int nTime = fastftol_positive(GetCurTimeSec());
  618.  
  619.         // support timer reset
  620.         m_nLastTimeUsed = min(m_nLastTimeUsed, nTime);
  621.  
  622.         if (m_nLastTimeUsed < (nTime - 16) && fDistanse > 512)
  623.         {
  624.                 // try to release vert buffer if not in use int time
  625.                 ReleaseHeightMapGeometry();
  626.         }
  627. }
  628.  
  629. void CTerrainNode::RemoveProcObjects(bool bRecursive, bool bReleaseAllObjects)
  630. {
  631.         FUNCTION_PROFILER_3DENGINE;
  632.  
  633.         // remove procedurally placed objects
  634.         if (m_bProcObjectsReady)
  635.         {
  636.                 if (m_pProcObjPoolPtr && bReleaseAllObjects)
  637.                 {
  638.                         m_pProcObjPoolPtr->ReleaseAllObjects();
  639.                         m_pProcObjPoolMan->ReleaseObject(m_pProcObjPoolPtr);
  640.                         m_pProcObjPoolPtr = NULL;
  641.                 }
  642.  
  643.                 m_bProcObjectsReady = false;
  644.         }
  645.  
  646.         if (bRecursive && m_pChilds)
  647.                 for (int i = 0; i < 4; i++)
  648.                         m_pChilds[i].RemoveProcObjects(bRecursive);
  649. }
  650.  
  651. void CTerrainNode::SetChildsLod(int nNewGeomLOD, const SRenderingPassInfo& passInfo)
  652. {
  653.         m_cNewGeomMML = nNewGeomLOD;
  654.         m_nSetLodFrameId = passInfo.GetMainFrameID();
  655.  
  656.         if (m_pChilds)
  657.         {
  658.                 for (int i = 0; i < 4; i++)
  659.                 {
  660.                         m_pChilds[i].m_cNewGeomMML = nNewGeomLOD;
  661.                         m_pChilds[i].m_nSetLodFrameId = passInfo.GetMainFrameID();
  662.                 }
  663.         }
  664. }
  665.  
  666. int CTerrainNode::GetAreaLOD(const SRenderingPassInfo& passInfo)
  667. {
  668. #if 0 // temporariliy disabled
  669.         int nResult = MML_NOT_SET;
  670.         CTerrainNode* pNode = this;
  671.         while (pNode)
  672.         {
  673.                 if (pNode->m_nSetLodFrameId == passInfo.GetMainFrameID())
  674.                 {
  675.                         nResult = pNode->m_cNewGeomMML;
  676.                         break;
  677.                 }
  678.                 pNode = pNode->m_pParent;
  679.         }
  680.         if (pNode && m_nSetLodFrameId != passInfo.GetMainFrameID())
  681.         {
  682.                 m_cNewGeomMML = nResult;
  683.                 m_nSetLodFrameId = passInfo.GetMainFrameID();
  684.         }
  685.         return nResult;
  686. #else
  687.         if (m_nSetLodFrameId == passInfo.GetMainFrameID())
  688.                 return m_cNewGeomMML;
  689.         return MML_NOT_SET;
  690. #endif
  691. }
  692.  
  693. bool CTerrainNode::RenderNodeHeightmap(const SRenderingPassInfo& passInfo)
  694. {
  695.         FUNCTION_PROFILER_3DENGINE;
  696.         bool bMeshIsUpToDate = true; // actually bUpdateNOTRequired
  697.  
  698.         if (m_arrfDistance[passInfo.GetRecursiveLevel()] < 8) // make sure near sectors are always potentially visible
  699.                 m_nLastTimeUsed = fastftol_positive(GetCurTimeSec());
  700.  
  701.         m_nLastTimeUsed = fastftol_positive(GetCurTimeSec());
  702.  
  703.         if (!GetVisAreaManager()->IsOutdoorAreasVisible())
  704.                 return true; // all fine, no update needed
  705.  
  706.         const CCamera& rCamera = passInfo.GetCamera();
  707.         if (GetCVars()->e_TerrainDrawThisSectorOnly)
  708.         {
  709.                 if (
  710.                   rCamera.GetPosition().x > GetBBox().max.x ||
  711.                   rCamera.GetPosition().x < GetBBox().min.x ||
  712.                   rCamera.GetPosition().y > GetBBox().max.y ||
  713.                   rCamera.GetPosition().y < GetBBox().min.y)
  714.                         return true;
  715.         }
  716.  
  717.         SetupTexturing(false, passInfo);
  718.  
  719.         bMeshIsUpToDate = RenderSector(passInfo);
  720.  
  721.         if (GetCVars()->e_TerrainBBoxes)
  722.         {
  723.                 ColorB colour = ColorB(255 * ((m_nTreeLevel & 1) > 0), 255 * ((m_nTreeLevel & 2) > 0), 255, 255);
  724.                 GetRenderer()->GetIRenderAuxGeom()->DrawAABB(GetBBox(), false, colour, eBBD_Faceted);
  725.                 if (GetCVars()->e_TerrainBBoxes == 3 && m_rangeInfo.nSize)
  726.                         IRenderAuxText::DrawLabelF(GetBBox().GetCenter(), 2, "%dx%d", m_rangeInfo.nSize, m_rangeInfo.nSize);
  727.         }
  728.  
  729.         if (GetCVars()->e_TerrainDetailMaterialsDebug)
  730.         {
  731.                 int nLayersNum = 0;
  732.                 for (int i = 0; i < m_lstSurfaceTypeInfo.Count(); i++)
  733.                 {
  734.                         if (m_lstSurfaceTypeInfo[i].HasRM() && m_lstSurfaceTypeInfo[i].pSurfaceType->HasMaterial())
  735.                                 if (m_lstSurfaceTypeInfo[i].GetIndexCount())
  736.                                         nLayersNum++;
  737.                 }
  738.  
  739.                 if (nLayersNum >= GetCVars()->e_TerrainDetailMaterialsDebug)
  740.                 {
  741.                         GetRenderer()->GetIRenderAuxGeom()->DrawAABB(GetBBox(), false, ColorB(255 * ((nLayersNum & 1) > 0), 255 * ((nLayersNum & 2) > 0), 255, 255), eBBD_Faceted);
  742.                         IRenderAuxText::DrawLabelF(GetBBox().GetCenter(), 2, "%d", nLayersNum);
  743.                 }
  744.         }
  745.  
  746.         // pre-cache surface types
  747.         for (int s = 0; s < SRangeInfo::e_hole; s++)
  748.         {
  749.                 SSurfaceType* pSurf = &Cry3DEngineBase::GetTerrain()->m_SSurfaceType[m_nSID][s];
  750.  
  751.                 if (pSurf->HasMaterial())
  752.                 {
  753.                         uint8 szProj[] = "XYZ";
  754.  
  755.                         for (int p = 0; p < 3; p++)
  756.                         {
  757.                                 if (CMatInfo* pMatInfo = (CMatInfo*)(IMaterial*)pSurf->GetMaterialOfProjection(szProj[p]))
  758.                                 {
  759.                                         pMatInfo->PrecacheMaterial(GetDistance(passInfo), NULL, GetDistance(passInfo) < 32.f);
  760.                                 }
  761.                         }
  762.                 }
  763.         }
  764.  
  765.         return bMeshIsUpToDate;
  766. }
  767.  
  768. float CTerrainNode::GetSurfaceTypeAmount(Vec3 vPos, int nSurfType)
  769. {
  770.         float fUnitSize = (float)GetTerrain()->GetHeightMapUnitSize();
  771.         vPos *= 1.f / fUnitSize;
  772.  
  773.         int x1 = int(vPos.x);
  774.         int y1 = int(vPos.y);
  775.         int x2 = int(vPos.x + 1);
  776.         int y2 = int(vPos.y + 1);
  777.  
  778.         float dx = vPos.x - x1;
  779.         float dy = vPos.y - y1;
  780.  
  781.         float s00 = GetTerrain()->GetSurfaceTypeID((int)(x1 * fUnitSize), (int)(y1 * fUnitSize), m_nSID) == nSurfType;
  782.         float s01 = GetTerrain()->GetSurfaceTypeID((int)(x1 * fUnitSize), (int)(y2 * fUnitSize), m_nSID) == nSurfType;
  783.         float s10 = GetTerrain()->GetSurfaceTypeID((int)(x2 * fUnitSize), (int)(y1 * fUnitSize), m_nSID) == nSurfType;
  784.         float s11 = GetTerrain()->GetSurfaceTypeID((int)(x2 * fUnitSize), (int)(y2 * fUnitSize), m_nSID) == nSurfType;
  785.  
  786.         if (s00 || s01 || s10 || s11)
  787.         {
  788.                 float s0 = s00 * (1.f - dy) + s01 * dy;
  789.                 float s1 = s10 * (1.f - dy) + s11 * dy;
  790.                 float res = s0 * (1.f - dx) + s1 * dx;
  791.                 return res;
  792.         }
  793.  
  794.         return 0;
  795. }
  796.  
  797. bool CTerrainNode::CheckUpdateProcObjects(const SRenderingPassInfo& passInfo)
  798. {
  799.         if (GetCVars()->e_TerrainDrawThisSectorOnly)
  800.         {
  801.                 const CCamera& rCamera = passInfo.GetCamera();
  802.                 if (
  803.                   rCamera.GetPosition().x > GetBBox().max.x ||
  804.                   rCamera.GetPosition().x < GetBBox().min.x ||
  805.                   rCamera.GetPosition().y > GetBBox().max.y ||
  806.                   rCamera.GetPosition().y < GetBBox().min.y)
  807.                         return false;
  808.         }
  809.  
  810.         if (m_bProcObjectsReady)
  811.                 return false;
  812.  
  813.         FUNCTION_PROFILER_3DENGINE;
  814.  
  815.         if (m_pProcObjPoolPtr)
  816.         {
  817.                 m_pProcObjPoolPtr->ReleaseAllObjects();
  818.                 m_pProcObjPoolMan->ReleaseObject(m_pProcObjPoolPtr);
  819.                 m_pProcObjPoolPtr = NULL;
  820.         }
  821.  
  822.         int nInstancesCounter = 0;
  823.  
  824.         CMTRand_int32 rndGen(gEnv->bNoRandomSeed ? 0 : m_nOriginX + m_nOriginY);
  825.  
  826.         float nSectorSize = (float)(CTerrain::GetSectorSize() << m_nTreeLevel);
  827.         for (int nLayer = 0; nLayer < m_lstSurfaceTypeInfo.Count(); nLayer++)
  828.         {
  829.                 for (int g = 0; g < m_lstSurfaceTypeInfo[nLayer].pSurfaceType->lstnVegetationGroups.Count(); g++)
  830.                         if (m_lstSurfaceTypeInfo[nLayer].pSurfaceType->lstnVegetationGroups[g] >= 0)
  831.                         {
  832.                                 int nGroupId = m_lstSurfaceTypeInfo[nLayer].pSurfaceType->lstnVegetationGroups[g];
  833.                                 assert(m_nSID < GetObjManager()->m_lstStaticTypes.Count() && nGroupId >= 0);
  834.                                 if (m_nSID >= GetObjManager()->m_lstStaticTypes.Count() || nGroupId < 0)
  835.                                         continue;
  836.                                 StatInstGroup* pGroup = std::find_if(GetObjManager()->m_lstStaticTypes[m_nSID].begin(), GetObjManager()->m_lstStaticTypes[m_nSID].end(), [nGroupId](StatInstGroup& a) { return a.nID == nGroupId; });
  837.                                 if (pGroup == GetObjManager()->m_lstStaticTypes[m_nSID].end() || !pGroup->GetStatObj() || pGroup->fSize <= 0)
  838.                                         continue;
  839.  
  840.                                 if (!CheckMinSpec(pGroup->minConfigSpec)) // Check min spec of this group.
  841.                                         continue;
  842.  
  843.                                 // distribute objects into different tree levels based on object size
  844.  
  845.                                 float fSectorViewDistMax = GetCVars()->e_ProcVegetationMaxViewDistance * (GetBBox().GetSize().x / 64.f);
  846.                                 float fSectorViewDistMin = fSectorViewDistMax * 0.5f;
  847.                                 float fVegMaxViewDist = pGroup->fVegRadius * pGroup->fSize * pGroup->fMaxViewDistRatio * GetCVars()->e_ViewDistRatioVegetation;
  848.  
  849.                                 if (fVegMaxViewDist > fSectorViewDistMax && m_nTreeLevel < (GetCVars()->GetCVars()->e_ProcVegetationMaxCacheLevels - 1))
  850.                                         continue;
  851.                                 if (fVegMaxViewDist < fSectorViewDistMin && m_nTreeLevel > 0)
  852.                                         continue;
  853.  
  854.                                 if (GetCVars()->e_ProcVegetation >= 3)
  855.                                         if (m_nTreeLevel != GetCVars()->e_ProcVegetation - 3)
  856.                                                 continue;
  857.  
  858.                                 if (pGroup->fDensity < 0.5f)
  859.                                         pGroup->fDensity = 0.5f;
  860.  
  861.                                 float fMinX = (float)m_nOriginX;
  862.                                 float fMinY = (float)m_nOriginY;
  863.                                 float fMaxX = (float)(m_nOriginX + nSectorSize);
  864.                                 float fMaxY = (float)(m_nOriginY + nSectorSize);
  865.  
  866.                                 for (float fX = fMinX; fX < fMaxX; fX += pGroup->fDensity)
  867.                                 {
  868.                                         for (float fY = fMinY; fY < fMaxY; fY += pGroup->fDensity)
  869.                                         {
  870.                                                 Vec3 vPos(fX + (rndGen.GenerateFloat() - 0.5f) * pGroup->fDensity, fY + (rndGen.GenerateFloat() - 0.5f) * pGroup->fDensity, 0);
  871.                                                 vPos.x = CLAMP(vPos.x, fMinX, fMaxX);
  872.                                                 vPos.y = CLAMP(vPos.y, fMinY, fMaxY);
  873.  
  874.                                                 {
  875.                                                         // filtered surface type lockup
  876.                                                         float fSurfaceTypeAmount = GetSurfaceTypeAmount(vPos, m_lstSurfaceTypeInfo[nLayer].pSurfaceType->ucThisSurfaceTypeId);
  877.                                                         if (fSurfaceTypeAmount <= 0.5)
  878.                                                                 continue;
  879.  
  880.                                                         vPos.z = GetTerrain()->GetZApr(vPos.x, vPos.y, m_nSID);
  881.                                                 }
  882.  
  883.                                                 Vec3 vWPos = GetTerrain()->m_arrSegmentOrigns[m_nSID] + vPos;
  884.                                                 if (vWPos.x < 0 || vWPos.x >= CTerrain::GetTerrainSize() || vWPos.y < 0 || vWPos.y >= CTerrain::GetTerrainSize())
  885.                                                         continue;
  886.  
  887.                                                 float fScale = pGroup->fSize + (rndGen.GenerateFloat() - 0.5f) * pGroup->fSizeVar;
  888.                                                 if (fScale <= 0)
  889.                                                         continue;
  890.  
  891.                                                 if (vWPos.z < pGroup->fElevationMin || vWPos.z > pGroup->fElevationMax)
  892.                                                         continue;
  893.  
  894.                                                 // check slope range
  895.                                                 if (pGroup->fSlopeMin != 0 || pGroup->fSlopeMax != 255)
  896.                                                 {
  897.                                                         int nStep = CTerrain::GetHeightMapUnitSize();
  898.                                                         int x = (int)fX;
  899.                                                         int y = (int)fY;
  900.  
  901.                                                         // calculate surface normal
  902.                                                         float sx;
  903.                                                         if ((x + nStep) < CTerrain::GetTerrainSize() && x >= nStep)
  904.                                                                 sx = GetTerrain()->GetZ(x + nStep, y, m_nSID) - GetTerrain()->GetZ(x - nStep, y, m_nSID);
  905.                                                         else
  906.                                                                 sx = 0;
  907.  
  908.                                                         float sy;
  909.                                                         if ((y + nStep) < CTerrain::GetTerrainSize() && y >= nStep)
  910.                                                                 sy = GetTerrain()->GetZ(x, y + nStep, m_nSID) - GetTerrain()->GetZ(x, y - nStep, m_nSID);
  911.                                                         else
  912.                                                                 sy = 0;
  913.  
  914.                                                         Vec3 vNormal = Vec3(-sx, -sy, nStep * 2.0f);
  915.                                                         vNormal.NormalizeFast();
  916.  
  917.                                                         float fSlope = (1 - vNormal.z) * 255;
  918.                                                         if (fSlope < pGroup->fSlopeMin || fSlope > pGroup->fSlopeMax)
  919.                                                                 continue;
  920.                                                 }
  921.  
  922.                                                 if (pGroup->fVegRadius * fScale < GetCVars()->e_VegetationMinSize)
  923.                                                         continue; // skip creation of very small objects
  924.  
  925.                                                 if (!m_pProcObjPoolPtr)
  926.                                                         m_pProcObjPoolPtr = m_pProcObjPoolMan->GetObject();
  927.  
  928.                                                 if (!m_pProcObjPoolPtr)
  929.                                                 {
  930.                                                         m_bProcObjectsReady = false;
  931.                                                         return true;
  932.                                                 }
  933.  
  934.                                                 CVegetation* pEnt = m_pProcObjPoolPtr->AllocateProcObject(m_nSID);
  935.                                                 assert(pEnt);
  936.  
  937.                                                 pEnt->SetScale(fScale);
  938.                                                 pEnt->m_vPos = vWPos;
  939.  
  940.                                                 int nGroupIndex = static_cast<int>(std::distance(GetObjManager()->m_lstStaticTypes[m_nSID].begin(), pGroup));
  941.                                                 pEnt->SetStatObjGroupIndex(nGroupIndex);
  942.  
  943.                                                 const uint32 nRnd = rndGen.GenerateUint32();
  944.                                                 const bool bRandomRotation = pGroup->bRandomRotation;
  945.                                                 const int32 nRotationRange = pGroup->nRotationRangeToTerrainNormal;
  946.  
  947.                                                 if (bRandomRotation || nRotationRange >= 360)
  948.                                                 {
  949.                                                         pEnt->m_ucAngle = static_cast<byte>(nRnd);
  950.                                                 }
  951.                                                 else if (nRotationRange > 0)
  952.                                                 {
  953.                                                         const Vec3 vTerrainNormal = Get3DEngine()->GetTerrainSurfaceNormal(vPos);
  954.  
  955.                                                         if (abs(vTerrainNormal.x) == 0.f && abs(vTerrainNormal.y) == 0.f)
  956.                                                         {
  957.                                                                 pEnt->m_ucAngle = static_cast<byte>(nRnd);
  958.                                                         }
  959.                                                         else
  960.                                                         {
  961.                                                                 const float rndDegree = (float)-nRotationRange * 0.5f + (float)(nRnd % (uint32)nRotationRange);
  962.                                                                 const float finaleDegree = RAD2DEG(atan2f(vTerrainNormal.y, vTerrainNormal.x)) + rndDegree;
  963.                                                                 pEnt->m_ucAngle = (byte)((finaleDegree / 360.0f) * 255.0f);
  964.                                                         }
  965.                                                 }
  966.  
  967.                                                 AABB aabb = pEnt->CalcBBox();
  968.  
  969.                                                 pEnt->SetRndFlags(ERF_PROCEDURAL, true);
  970.  
  971.                                                 pEnt->m_fWSMaxViewDist = pEnt->GetMaxViewDist(); // note: duplicated
  972.  
  973.                                                 pEnt->UpdateRndFlags();
  974.  
  975.                                                 pEnt->Physicalize(true);
  976.  
  977.                                                 float fObjRadius = aabb.GetRadius();
  978.                                                 if (fObjRadius > MAX_VALID_OBJECT_VOLUME || !_finite(fObjRadius) || fObjRadius <= 0)
  979.                                                 {
  980.                                                         Warning("CTerrainNode::CheckUpdateProcObjects: Object has invalid bbox: %s,%s, GetRadius() = %.2f",
  981.                                                                 pEnt->GetName(), pEnt->GetEntityClassName(), fObjRadius);
  982.                                                 }
  983.  
  984.                                                 Get3DEngine()->m_pObjectsTree[m_nSID]->InsertObject(pEnt, aabb, fObjRadius, aabb.GetCenter());
  985.  
  986.                                                 nInstancesCounter++;
  987.                                                 if (nInstancesCounter >= (MAX_PROC_OBJ_CHUNKS_NUM / MAX_PROC_SECTORS_NUM) * GetCVars()->e_ProcVegetationMaxObjectsInChunk)
  988.                                                 {
  989.                                                         m_bProcObjectsReady = true;
  990.                                                         return true;
  991.                                                 }
  992.                                         }
  993.                                 }
  994.                         }
  995.         }
  996.  
  997.         m_bProcObjectsReady = true;
  998.  
  999.         //      GetISystem()->VTunePause();
  1000.         return true;
  1001. }
  1002.  
  1003. CVegetation* CProcObjSector::AllocateProcObject(int nSID)
  1004. {
  1005.         FUNCTION_PROFILER_3DENGINE;
  1006.  
  1007.         // find pool id
  1008.         int nLastPoolId = m_nProcVegetNum / GetCVars()->e_ProcVegetationMaxObjectsInChunk;
  1009.         if (nLastPoolId >= m_ProcVegetChunks.Count())
  1010.         {
  1011.                 //PrintMessage("CTerrainNode::AllocateProcObject: Sector(%d,%d) %d objects",m_nOriginX,m_nOriginY,m_nProcVegetNum);
  1012.                 m_ProcVegetChunks.PreAllocate(nLastPoolId + 1, nLastPoolId + 1);
  1013.                 SProcObjChunk* pChunk = m_ProcVegetChunks[nLastPoolId] = CTerrainNode::m_pProcObjChunkPool->GetObject();
  1014.  
  1015.                 // init objects
  1016.                 for (int o = 0; o < GetCVars()->e_ProcVegetationMaxObjectsInChunk; o++)
  1017.                         pChunk->m_pInstances[o].Init();
  1018.         }
  1019.  
  1020.         // find empty slot id and return pointer to it
  1021.         int nNextSlotInPool = m_nProcVegetNum - nLastPoolId * GetCVars()->e_ProcVegetationMaxObjectsInChunk;
  1022.         CVegetation* pObj = &(m_ProcVegetChunks[nLastPoolId]->m_pInstances)[nNextSlotInPool];
  1023. #ifdef SEG_WORLD
  1024.         pObj->m_nStaticTypeSlot = nSID;
  1025. #endif
  1026.         m_nProcVegetNum++;
  1027.         return pObj;
  1028. }
  1029.  
  1030. void CProcObjSector::ReleaseAllObjects()
  1031. {
  1032.         for (int i = 0; i < m_ProcVegetChunks.Count(); i++)
  1033.         {
  1034.                 SProcObjChunk* pChunk = m_ProcVegetChunks[i];
  1035.                 for (int o = 0; o < pChunk->nAllocatedItems; o++)
  1036.                         pChunk->m_pInstances[o].ShutDown();
  1037.                 CTerrainNode::m_pProcObjChunkPool->ReleaseObject(m_ProcVegetChunks[i]);
  1038.         }
  1039.         m_ProcVegetChunks.Clear();
  1040.         m_nProcVegetNum = 0;
  1041. }
  1042.  
  1043. void CProcObjSector::GetMemoryUsage(ICrySizer* pSizer) const
  1044. {
  1045.         pSizer->AddObject(this, sizeof(*this));
  1046.  
  1047.         pSizer->AddObject(m_ProcVegetChunks);
  1048.  
  1049.         for (int i = 0; i < m_ProcVegetChunks.Count(); i++)
  1050.                 pSizer->AddObject(m_ProcVegetChunks[i], sizeof(CVegetation) * GetCVars()->e_ProcVegetationMaxObjectsInChunk);
  1051. }
  1052.  
  1053. CProcObjSector::~CProcObjSector()
  1054. {
  1055.         FUNCTION_PROFILER_3DENGINE;
  1056.  
  1057.         ReleaseAllObjects();
  1058. }
  1059.  
  1060. void SProcObjChunk::GetMemoryUsage(class ICrySizer* pSizer) const
  1061. {
  1062.         pSizer->AddObject(this, sizeof(*this));
  1063.  
  1064.         if (m_pInstances)
  1065.                 pSizer->AddObject(m_pInstances, sizeof(CVegetation) * GetCVars()->e_ProcVegetationMaxObjectsInChunk);
  1066. }
  1067.  
  1068. void CTerrainNode::IntersectTerrainAABB(const AABB& aabbBox, PodArray<CTerrainNode*>& lstResult)
  1069. {
  1070.         if (GetBBox().IsIntersectBox(aabbBox))
  1071.         {
  1072.                 lstResult.Add(this);
  1073.                 if (m_pChilds)
  1074.                         for (int i = 0; i < 4; i++)
  1075.                                 m_pChilds[i].IntersectTerrainAABB(aabbBox, lstResult);
  1076.         }
  1077. }
  1078.  
  1079. /*
  1080.    int CTerrainNode__Cmp_SSurfaceType_UnitsNum(const void* v1, const void* v2)
  1081.    {
  1082.    SSurfaceType * p1 = *(SSurfaceType **)v1;
  1083.    SSurfaceType * p2 = *(SSurfaceType **)v2;
  1084.  
  1085.    assert(p1 && p2);
  1086.  
  1087.    if(p1->nUnitsNum > p2->nUnitsNum)
  1088.     return -1;
  1089.    else if(p1->nUnitsNum < p2->nUnitsNum)
  1090.     return 1;
  1091.  
  1092.    return 0;
  1093.    }
  1094.  */
  1095. /*
  1096.    int CTerrainNode__Cmp_TerrainSurfaceLayerAmount_UnitsNum(const void* v1, const void* v2)
  1097.    {
  1098.    TerrainSurfaceLayerAmount * p1 = (TerrainSurfaceLayerAmount *)v1;
  1099.    TerrainSurfaceLayerAmount * p2 = (TerrainSurfaceLayerAmount *)v2;
  1100.  
  1101.    assert(p1 && p2);
  1102.  
  1103.    if(p1->nUnitsNum > p2->nUnitsNum)
  1104.     return -1;
  1105.    else if(p1->nUnitsNum < p2->nUnitsNum)
  1106.     return 1;
  1107.  
  1108.    return 0;
  1109.    }
  1110.  */
  1111. void CTerrainNode::UpdateDetailLayersInfo(bool bRecursive)
  1112. {
  1113.         FUNCTION_PROFILER_3DENGINE;
  1114.  
  1115.         if (m_pChilds)
  1116.         {
  1117.                 // accumulate surface info from childs
  1118.                 if (bRecursive)
  1119.                 {
  1120.                         for (int nChild = 0; nChild < 4; nChild++)
  1121.                                 m_pChilds[nChild].UpdateDetailLayersInfo(bRecursive);
  1122.                 }
  1123.  
  1124.                 m_bHasHoles = 0;
  1125.  
  1126.                 static PodArray<SSurfaceType*> lstChildsLayers;
  1127.                 lstChildsLayers.Clear();
  1128.                 for (int nChild = 0; nChild < 4; nChild++)
  1129.                 {
  1130.                         if (m_pChilds[nChild].m_bHasHoles)
  1131.                                 m_bHasHoles = 1;
  1132.  
  1133.                         for (int i = 0; i < m_pChilds[nChild].m_lstSurfaceTypeInfo.Count(); i++)
  1134.                         {
  1135.                                 SSurfaceType* pType = m_pChilds[nChild].m_lstSurfaceTypeInfo[i].pSurfaceType;
  1136.                                 assert(pType);
  1137.                                 if (lstChildsLayers.Find(pType) < 0 && pType->HasMaterial())
  1138.                                         lstChildsLayers.Add(pType);
  1139.                         }
  1140.                 }
  1141.  
  1142.                 if (m_bHasHoles)
  1143.                         if (m_pChilds[0].m_bHasHoles == 2)
  1144.                                 if (m_pChilds[1].m_bHasHoles == 2)
  1145.                                         if (m_pChilds[2].m_bHasHoles == 2)
  1146.                                                 if (m_pChilds[3].m_bHasHoles == 2)
  1147.                                                         m_bHasHoles = 2;
  1148.  
  1149.                 for (int i = 0; i < m_lstSurfaceTypeInfo.Count(); i++)
  1150.                         m_lstSurfaceTypeInfo[i].DeleteRenderMeshes(GetRenderer());
  1151.                 m_lstSurfaceTypeInfo.Clear();
  1152.  
  1153.                 m_lstSurfaceTypeInfo.PreAllocate(lstChildsLayers.Count());
  1154.  
  1155.                 assert(lstChildsLayers.Count() <= SRangeInfo::e_max_surface_types);
  1156.  
  1157.                 for (int i = 0; i < lstChildsLayers.Count(); i++)
  1158.                 {
  1159.                         SSurfaceTypeInfo si;
  1160.                         si.pSurfaceType = lstChildsLayers[i];
  1161.                         m_lstSurfaceTypeInfo.Add(si);
  1162.                 }
  1163.         }
  1164.         else
  1165.         {
  1166.                 // find all used surface types
  1167.                 int arrSurfaceTypesInSector[SRangeInfo::e_max_surface_types];
  1168.                 for (int i = 0; i < SRangeInfo::e_max_surface_types; i++)
  1169.                         arrSurfaceTypesInSector[i] = 0;
  1170.  
  1171.                 m_bHasHoles = 0;
  1172.  
  1173.                 for (int X = m_nOriginX; X <= m_nOriginX + CTerrain::GetSectorSize(); X += CTerrain::GetHeightMapUnitSize())
  1174.                         for (int Y = m_nOriginY; Y <= m_nOriginY + CTerrain::GetSectorSize(); Y += CTerrain::GetHeightMapUnitSize())
  1175.                         {
  1176.                                 uint8 ucSurfaceTypeID = GetTerrain()->GetSurfaceTypeID(X, Y, m_nSID);
  1177.                                 if (SRangeInfo::e_hole == ucSurfaceTypeID)
  1178.                                         m_bHasHoles = 1;
  1179.                                 CRY_ASSERT(ucSurfaceTypeID < SRangeInfo::e_max_surface_types);
  1180.                                 arrSurfaceTypesInSector[ucSurfaceTypeID]++;
  1181.                         }
  1182.  
  1183.                 if (arrSurfaceTypesInSector[SRangeInfo::e_hole] == (CTerrain::GetSectorSize() / CTerrain::GetHeightMapUnitSize() + 1) * (CTerrain::GetSectorSize() / CTerrain::GetHeightMapUnitSize() + 1))
  1184.                         m_bHasHoles = 2; // only holes
  1185.  
  1186.                 for (int i = 0; i < m_lstSurfaceTypeInfo.Count(); i++)
  1187.                         m_lstSurfaceTypeInfo[i].DeleteRenderMeshes(GetRenderer());
  1188.                 m_lstSurfaceTypeInfo.Clear();
  1189.  
  1190.                 int nSurfCount = 0;
  1191.                 for (int i = 0; i < SRangeInfo::e_max_surface_types; i++)
  1192.                         if (arrSurfaceTypesInSector[i])
  1193.                         {
  1194.                                 SSurfaceTypeInfo si;
  1195.                                 si.pSurfaceType = &GetTerrain()->m_SSurfaceType[m_nSID][i];
  1196.                                 if (si.pSurfaceType->HasMaterial())
  1197.                                         nSurfCount++;
  1198.                         }
  1199.  
  1200.                 m_lstSurfaceTypeInfo.PreAllocate(nSurfCount);
  1201.  
  1202.                 for (int i = 0; i < SRangeInfo::e_max_surface_types; i++)
  1203.                         if (arrSurfaceTypesInSector[i])
  1204.                         {
  1205.                                 SSurfaceTypeInfo si;
  1206.                                 si.pSurfaceType = &GetTerrain()->m_SSurfaceType[m_nSID][i];
  1207.                                 if (si.pSurfaceType->HasMaterial())
  1208.                                         m_lstSurfaceTypeInfo.Add(si);
  1209.                         }
  1210.  
  1211.                 // If necessary, fix the sector palette by removing any unused/wrong entries:
  1212.                 if (m_rangeInfo.pSTPalette)
  1213.                 {
  1214.                         for (int i = 0; i < SRangeInfo::e_index_undefined; ++i)
  1215.                         {
  1216.                                 const uchar sType = m_rangeInfo.pSTPalette[i];
  1217.  
  1218.                                 if (sType < SRangeInfo::e_undefined && !arrSurfaceTypesInSector[sType] ||
  1219.                                     !GetTerrain()->m_SSurfaceType[m_nSID][sType].HasMaterial())
  1220.                                         m_rangeInfo.pSTPalette[i] = SRangeInfo::e_undefined;
  1221.                         }
  1222.                 }
  1223.         }
  1224. }
  1225.  
  1226. void CTerrainNode::IntersectWithShadowFrustum(bool bAllIn, PodArray<IShadowCaster*>* plstResult, ShadowMapFrustum* pFrustum, const float fHalfGSMBoxSize, const SRenderingPassInfo& passInfo)
  1227. {
  1228.         if (bAllIn || (pFrustum && pFrustum->IntersectAABB(GetBBox(), &bAllIn)))
  1229.         {
  1230.                 float fSectorSize = GetBBox().max.x - GetBBox().min.x;
  1231.                 if (m_pChilds && (fSectorSize*GetCVars()->e_TerrainMeshInstancingShadowLodRatio > fHalfGSMBoxSize || (m_nTreeLevel > GetCVars()->e_TerrainMeshInstancingMinLod && pFrustum->IsCached())))
  1232.                 {
  1233.                         for (int i = 0; i < 4; i++)
  1234.                                 m_pChilds[i].IntersectWithShadowFrustum(bAllIn, plstResult, pFrustum, fHalfGSMBoxSize, passInfo);
  1235.                 }
  1236.                 else
  1237.                 {
  1238.                         plstResult->Add(this);
  1239.                 }
  1240.         }
  1241. }
  1242.  
  1243. void CTerrainNode::IntersectWithBox(const AABB& aabbBox, PodArray<CTerrainNode*>* plstResult)
  1244. {
  1245.         if (aabbBox.IsIntersectBox(GetBBox()))
  1246.         {
  1247.                 for (int i = 0; m_pChilds && i < 4; i++)
  1248.                         m_pChilds[i].IntersectWithBox(aabbBox, plstResult);
  1249.  
  1250.                 plstResult->Add(this);
  1251.         }
  1252. }
  1253.  
  1254. CTerrainNode* CTerrainNode::FindMinNodeContainingBox(const AABB& aabbBox)
  1255. {
  1256.         AABB boxWS = GetBBox();
  1257.  
  1258.         if (aabbBox.min.x < boxWS.min.x - 0.01f || aabbBox.min.y < boxWS.min.y - 0.01f ||
  1259.             aabbBox.max.x > boxWS.max.x + 0.01f || aabbBox.max.y > boxWS.max.y + 0.01f)
  1260.                 return NULL;
  1261.  
  1262.         if (m_pChilds)
  1263.                 for (int i = 0; i < 4; i++)
  1264.                         if (CTerrainNode* pRes = m_pChilds[i].FindMinNodeContainingBox(aabbBox))
  1265.                                 return pRes;
  1266.  
  1267.         return this;
  1268. }
  1269.  
  1270. void CTerrainNode::UnloadNodeTexture(bool bRecursive)
  1271. {
  1272.         if (m_pReadStream)
  1273.         {
  1274.                 // We don't need this stream anymore.
  1275.                 m_pReadStream->Abort();
  1276.                 m_pReadStream = NULL;
  1277.         }
  1278.  
  1279.         if (m_nNodeTexSet.nTex0)
  1280.                 m_pTerrain->m_texCache[0].ReleaseTexture(m_nNodeTexSet.nTex0, m_nNodeTexSet.nSlot0);
  1281.  
  1282.         if (m_nNodeTexSet.nTex1)
  1283.                 m_pTerrain->m_texCache[1].ReleaseTexture(m_nNodeTexSet.nTex1, m_nNodeTexSet.nSlot1);
  1284.  
  1285.         if (m_nNodeTexSet.nTex2)
  1286.                 m_pTerrain->m_texCache[2].ReleaseTexture(m_nNodeTexSet.nTex2, m_nNodeTexSet.nSlot2);
  1287.  
  1288.         if (m_nNodeTexSet.nTex0 && GetCVars()->e_TerrainTextureStreamingDebug == 2)
  1289.                 PrintMessage("Texture released %d, Level=%d", GetSecIndex(), m_nTreeLevel);
  1290.  
  1291.         m_nNodeTexSet = SSectorTextureSet();
  1292.  
  1293.         for (int i = 0; m_pChilds && bRecursive && i < 4; i++)
  1294.                 m_pChilds[i].UnloadNodeTexture(bRecursive);
  1295.  
  1296.         m_eTexStreamingStatus = ecss_NotLoaded;
  1297. }
  1298.  
  1299. void CTerrainNode::UpdateDistance(const SRenderingPassInfo& passInfo)
  1300. {
  1301.         m_arrfDistance[passInfo.GetRecursiveLevel()] = GetPointToBoxDistance(passInfo.GetCamera().GetPosition(), GetBBox());
  1302. }
  1303.  
  1304. const float CTerrainNode::GetDistance(const SRenderingPassInfo& passInfo)
  1305. {
  1306.         return m_arrfDistance[passInfo.GetRecursiveLevel()];
  1307. }
  1308.  
  1309. void CTerrainNode::GetMemoryUsage(ICrySizer* pSizer) const
  1310. {
  1311.         {
  1312.                 SIZER_COMPONENT_NAME(pSizer, "TerrainNodeSelf");
  1313.                 pSizer->AddObject(this, sizeof(*this));
  1314.         }
  1315.  
  1316.         {
  1317.                 SIZER_COMPONENT_NAME(pSizer, "SurfaceTypeInfo");
  1318.                 pSizer->AddObject(m_lstSurfaceTypeInfo);
  1319.         }
  1320.  
  1321.         {
  1322.                 SIZER_COMPONENT_NAME(pSizer, "HMData");
  1323.                 pSizer->AddObject(m_rangeInfo.pHMData, m_rangeInfo.nSize * m_rangeInfo.nSize * sizeof(m_rangeInfo.pHMData[0]));
  1324.         }
  1325.  
  1326.         {
  1327.                 SIZER_COMPONENT_NAME(pSizer, "GeomErrors");
  1328.                 pSizer->AddObject(m_pGeomErrors, GetTerrain()->m_nUnitsToSectorBitShift * sizeof(m_pGeomErrors[0]));
  1329.         }
  1330.  
  1331.         if (m_pLeafData)
  1332.         {
  1333.                 SIZER_COMPONENT_NAME(pSizer, "LeafData");
  1334.                 pSizer->AddObject(m_pLeafData, sizeof(*m_pLeafData));
  1335.         }
  1336.  
  1337.         // childs
  1338.         if (m_pChilds)
  1339.                 for (int i = 0; i < 4; i++)
  1340.                         m_pChilds[i].GetMemoryUsage(pSizer);
  1341. }
  1342.  
  1343. void CTerrainNode::GetResourceMemoryUsage(ICrySizer* pSizer, const AABB& cstAABB)
  1344. {
  1345.         size_t nCurrentChild(0);
  1346.         size_t nTotalChildren(4);
  1347.  
  1348.         SIZER_COMPONENT_NAME(pSizer, "CTerrainNode");
  1349.  
  1350.         if (m_pChilds)
  1351.                 for (nCurrentChild = 0; nCurrentChild < nTotalChildren; ++nCurrentChild)
  1352.                 {
  1353.                         m_pChilds[nCurrentChild].GetResourceMemoryUsage(pSizer, cstAABB);
  1354.                 }
  1355.  
  1356.         size_t nCurrentSurfaceTypeInfo(0);
  1357.         size_t nNumberOfSurfaceTypeInfo(0);
  1358.  
  1359.         nNumberOfSurfaceTypeInfo = m_lstSurfaceTypeInfo.size();
  1360.         for (nCurrentSurfaceTypeInfo = 0; nCurrentSurfaceTypeInfo < nNumberOfSurfaceTypeInfo; ++nCurrentSurfaceTypeInfo)
  1361.         {
  1362.                 SSurfaceTypeInfo& rSurfaceType = m_lstSurfaceTypeInfo[nCurrentSurfaceTypeInfo];
  1363.                 if (rSurfaceType.pSurfaceType)
  1364.                 {
  1365.                         if (rSurfaceType.pSurfaceType->pLayerMat)
  1366.                         {
  1367.                                 rSurfaceType.pSurfaceType->pLayerMat->GetResourceMemoryUsage(pSizer);
  1368.                         }
  1369.                 }
  1370.         }
  1371.  
  1372.         // Leaf data is dynamic, thus it's not being accounted now.
  1373.         //      if (m_pLeafData)
  1374.         //      {
  1375.         //      }
  1376. }
  1377.  
  1378. void CTerrainNode::Render(const SRendParams& RendParams, const SRenderingPassInfo& passInfo)
  1379. {
  1380.         FUNCTION_PROFILER_3DENGINE;
  1381.  
  1382.         if (GetCVars()->e_TerrainDrawThisSectorOnly)
  1383.         {
  1384.                 if (
  1385.                   passInfo.GetCamera().GetPosition().x > GetBBox().max.x ||
  1386.                   passInfo.GetCamera().GetPosition().x < GetBBox().min.x ||
  1387.                   passInfo.GetCamera().GetPosition().y > GetBBox().max.y ||
  1388.                   passInfo.GetCamera().GetPosition().y < GetBBox().min.y)
  1389.                         return; // false;
  1390.         }
  1391.  
  1392.         if (passInfo.IsShadowPass())
  1393.         {
  1394.                 // render shadow gen using fast path and mesh instancing
  1395.                 DrawArray(passInfo);
  1396.         }
  1397.         else
  1398.         {
  1399.                 CheckLeafData();
  1400.  
  1401.                 if (!RenderSector(passInfo) && m_pTerrain)
  1402.                         m_pTerrain->m_pTerrainUpdateDispatcher->QueueJob(this, passInfo);
  1403.         }
  1404.  
  1405.         m_nLastTimeUsed = fastftol_positive(GetCurTimeSec());
  1406. }
  1407.  
  1408. /*bool CTerrainNode::CheckUpdateLightMap()
  1409.    {
  1410.    Vec3 vSunDir = Get3DEngine()->GetSunDir().normalized();
  1411.  
  1412.    bool bUpdateIsRequired = m _nNodeTextureLastUsedFrameId>(passInfo.GetMainFrameID()-30) &&
  1413.     (GetSectorSizeInHeightmapUnits()>=TERRAIN_LM_TEX_RES && m_nNodeTextureOffset>=0) && !m_nNodeTexSet.nTex1;
  1414.  
  1415.    if(!bUpdateIsRequired)
  1416.     return true; // allow to go next node
  1417.  
  1418.    int nLM_Finished_Size = 0;
  1419.    int nCount = 0;
  1420.    float fStartTime = GetCurAsyncTimeSec();
  1421.    while(!nLM_Finished_Size && (GetCurAsyncTimeSec()-fStartTime) < 0.001f*GetCVars()->e_terrain_lm_gen_ms_per_frame)
  1422.    {
  1423.     nLM_Finished_Size = DoLightMapIncrementaly(m_nNodeTexSet.nLM_X, m_nNodeTexSet.nLM_Y, 512);
  1424.     nCount++;
  1425.    }
  1426.  
  1427.    if(nLM_Finished_Size)
  1428.    {
  1429.     if(m_nNodeTexSet.nTex1)
  1430.       GetRenderer()->RemoveTexture(m_nNodeTexSet.nTex1);
  1431.  
  1432.     m_nNodeTexSet.nTex1 = GetRenderer()->DownLoadToVideoMemory((uint8*)m_LightMap.GetData(), nLM_Finished_Size, nLM_Finished_Size,
  1433.       eTF_A8R8G8B8, eTF_A8R8G8B8, 0, false, FILTER_LINEAR);
  1434.  
  1435.     // Mark Vegetations Brightness As Un-compiled
  1436.     m_boxHeigtmap.min.z = max(0.f,m_boxHeigtmap.min.z);
  1437.  
  1438.     return true; // allow to go next node
  1439.    }
  1440.  
  1441.    return false; // more time is needed for this node
  1442.    }*/
  1443.  
  1444. bool CTerrainNode::CheckUpdateDiffuseMap()
  1445. {
  1446.         if (!m_nNodeTexSet.nTex0 && m_eTexStreamingStatus != ecss_Ready)
  1447.         {
  1448.                 // make texture loading once per several frames
  1449.                 CheckLeafData();
  1450.  
  1451.                 if (m_eTexStreamingStatus == ecss_NotLoaded)
  1452.                         StartSectorTexturesStreaming(Get3DEngine()->IsTerrainSyncLoad());
  1453.  
  1454.                 if (m_eTexStreamingStatus != ecss_Ready)
  1455.                         return false;
  1456.  
  1457.                 return false;
  1458.         }
  1459.  
  1460.         return true; // allow to go next node
  1461. }
  1462.  
  1463. bool CTerrainNode::AssignTextureFileOffset(int16*& pIndices, int16& nElementsLeft)
  1464. {
  1465.         m_nNodeTextureOffset = *pIndices;
  1466.  
  1467.         pIndices++;
  1468.         nElementsLeft--;
  1469.  
  1470.         for (int i = 0; i < 4; i++)
  1471.         {
  1472.                 if (*pIndices >= 0)
  1473.                 {
  1474.                         if (!m_pChilds)
  1475.                                 return false;
  1476.  
  1477.                         if (!m_pChilds[i].AssignTextureFileOffset(pIndices, nElementsLeft))
  1478.                                 return false;
  1479.                 }
  1480.                 else
  1481.                 {
  1482.                         pIndices++;
  1483.                         nElementsLeft--;
  1484.                 }
  1485.         }
  1486.  
  1487.         m_bMergeNotAllowed = false;
  1488.  
  1489.         return true;
  1490. }
  1491.  
  1492. int SSurfaceTypeInfo::GetIndexCount()
  1493. {
  1494.         int nCount = 0;
  1495.         for (int i = 0; i < 3; i++)
  1496.                 if (arrpRM[i])
  1497.                         nCount += arrpRM[i]->GetIndicesCount();
  1498.  
  1499.         return nCount;
  1500.  
  1501. }
  1502.  
  1503. void SSurfaceTypeInfo::DeleteRenderMeshes(IRenderer* pRend)
  1504. {
  1505.         for (int i = 0; i < 3; i++)
  1506.         {
  1507.                 arrpRM[i] = NULL;
  1508.         }
  1509. }
  1510.  
  1511. int CTerrainNode::GetSectorSizeInHeightmapUnits() const
  1512. {
  1513.         int nSectorSize = CTerrain::GetSectorSize() << m_nTreeLevel;
  1514.         return nSectorSize / CTerrain::GetHeightMapUnitSize();
  1515. }
  1516.  
  1517. SProcObjChunk::SProcObjChunk()
  1518. {
  1519.         nAllocatedItems = GetCVars()->e_ProcVegetationMaxObjectsInChunk;
  1520.         m_pInstances = new CVegetation[nAllocatedItems];
  1521. }
  1522.  
  1523. SProcObjChunk::~SProcObjChunk()
  1524. {
  1525.         delete[] m_pInstances;
  1526. }
  1527.  
  1528. CTerrainNode* CTerrain::FindMinNodeContainingBox(const AABB& someBox, int nSID)
  1529. {
  1530.         FUNCTION_PROFILER_3DENGINE;
  1531.         assert(nSID >= 0);
  1532.         CTerrainNode* pParentNode = GetParentNode(nSID);
  1533.         return pParentNode ? pParentNode->FindMinNodeContainingBox(someBox) : NULL;
  1534. }
  1535.  
  1536. int CTerrain::FindMinNodesContainingBox(const AABB& someBox, PodArray<CTerrainNode*>& arrNodes)
  1537. {
  1538.         // bad (slow) implementation, optimise if needed
  1539.         int nCount = 0;
  1540.         for (int nSID = 0; nSID < GetMaxSegmentsCount(); ++nSID)
  1541.         {
  1542.                 AABB aabbSeg;
  1543.                 if (!GetSegmentBounds(nSID, aabbSeg))
  1544.                         continue;
  1545.                 if (!someBox.IsIntersectBox(aabbSeg))
  1546.                         continue;
  1547.                 AABB aabb = someBox;
  1548.                 aabb.ClipToBox(aabbSeg);
  1549.                 //aabb.Move(-aabbSeg.min);
  1550.                 CTerrainNode* pn = FindMinNodeContainingBox(aabb, nSID);
  1551.                 assert(pn);
  1552.                 if (!pn)
  1553.                         continue;
  1554.                 arrNodes.Add(pn);
  1555.                 ++nCount;
  1556.         }
  1557.         return nCount;
  1558. }
  1559.  
  1560. void CTerrainNode::OffsetPosition(const Vec3& delta)
  1561. {
  1562. #ifdef SEG_WORLD
  1563.         for (int i = 0; i < m_lstSurfaceTypeInfo.Count(); ++i)
  1564.         {
  1565.                 for (int p = 0; p < 3; ++p)
  1566.                 {
  1567.                         if (IRenderMesh* pRM = m_lstSurfaceTypeInfo[i].arrpRM[p])
  1568.                         {
  1569.                                 pRM->OffsetPosition(delta);
  1570.                         }
  1571.                 }
  1572.         }
  1573.  
  1574.         if (m_pChilds)
  1575.                 for (int i = 0; i < 4; ++i)
  1576.                         m_pChilds[i].OffsetPosition(delta);
  1577. #endif
  1578. }
  1579.  
  1580. void CTerrainNode::FillBBox(AABB& aabb)
  1581. {
  1582.         aabb = GetBBox();
  1583. }
  1584.  
downloadterrain_node.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top