BVB Source Codes

CRYENGINE Show terran_edit.cpp Source code

Return Download CRYENGINE: download terran_edit.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:   terran_edit.cpp
  5. //  Version:     v1.00
  6. //  Created:     28/5/2001 by Vladimir Kajalin
  7. //  Compilers:   Visual Studio.NET
  8. //  Description: add/remove static objects, modify hmap (used by editor)
  9. // -------------------------------------------------------------------------
  10. //  History:
  11. //
  12. ////////////////////////////////////////////////////////////////////////////
  13.  
  14. #include "StdAfx.h"
  15.  
  16. #include "terrain.h"
  17. #include "terrain_sector.h"
  18. #include "StatObj.h"
  19. #include "ObjMan.h"
  20. #include "3dEngine.h"
  21. #include "Vegetation.h"
  22. #include "PolygonClipContext.h"
  23. #include "RoadRenderNode.h"
  24. #include "MergedMeshRenderNode.h"
  25. #include "MergedMeshGeometry.h"
  26. #include "Brush.h"
  27. #include "DecalRenderNode.h"
  28. #include "WaterVolumeRenderNode.h"
  29. #include <CryEntitySystem/IEntitySystem.h>
  30.  
  31. #define RAD2BYTE(x) ((x)* 255.0f / float(g_PI2))
  32. #define BYTE2RAD(x) ((x)* float(g_PI2) / 255.0f)
  33.  
  34. //////////////////////////////////////////////////////////////////////////
  35. IRenderNode* CTerrain::AddVegetationInstance(int nStaticGroupIndex, const Vec3& vPos, const float fScale, uint8 ucBright,
  36.                                              uint8 angle, uint8 angleX, uint8 angleY, int nSID)
  37. {
  38.         if (vPos.x <= 0 || vPos.y <= 0 || vPos.x >= CTerrain::GetTerrainSize() || vPos.y >= CTerrain::GetTerrainSize() || fScale * VEGETATION_CONV_FACTOR < 1.f)
  39.                 return 0;
  40.         IRenderNode* renderNode = NULL;
  41.  
  42.         assert(nSID >= 0 && nSID < GetObjManager()->m_lstStaticTypes.Count());
  43.  
  44.         if (nStaticGroupIndex < 0 || nStaticGroupIndex >= GetObjManager()->m_lstStaticTypes[nSID].Count())
  45.         {
  46.                 return 0;
  47.         }
  48.  
  49.         StatInstGroup& group = GetObjManager()->m_lstStaticTypes[nSID][nStaticGroupIndex];
  50.         if (!group.GetStatObj())
  51.         {
  52.                 Warning("I3DEngine::AddStaticObject: Attempt to add object of undefined type");
  53.                 return 0;
  54.         }
  55.         if (!group.bAutoMerged)
  56.         {
  57.                 CVegetation* pEnt = (CVegetation*)Get3DEngine()->CreateRenderNode(eERType_Vegetation);
  58.                 pEnt->SetScale(fScale);
  59.                 pEnt->m_vPos = vPos;
  60.                 pEnt->SetStatObjGroupIndex(nStaticGroupIndex);
  61.                 pEnt->m_ucAngle = angle;
  62.                 pEnt->m_ucAngleX = angleX;
  63.                 pEnt->m_ucAngleY = angleY;
  64.                 pEnt->CalcBBox();
  65.  
  66.                 float fEntLengthSquared = pEnt->GetBBox().GetSize().GetLengthSquared();
  67.                 if (fEntLengthSquared > MAX_VALID_OBJECT_VOLUME || !_finite(fEntLengthSquared) || fEntLengthSquared <= 0)
  68.                 {
  69.                         Warning("CTerrain::AddVegetationInstance: Object has invalid bbox: %s,%s, GetRadius() = %.2f",
  70.                                 pEnt->GetName(), pEnt->GetEntityClassName(), sqrt_tpl(fEntLengthSquared) * 0.5f);
  71.                 }
  72.  
  73.                 pEnt->Physicalize();
  74.                 Get3DEngine()->RegisterEntity(pEnt);
  75.                 renderNode = pEnt;
  76.         }
  77.         else
  78.         {
  79.                 SProcVegSample sample;
  80.                 sample.InstGroupId = nStaticGroupIndex;
  81.                 sample.pos = vPos;
  82.                 sample.scale = (uint8)SATURATEB(fScale * VEGETATION_CONV_FACTOR);
  83.                 Matrix33 mr = Matrix33::CreateRotationXYZ(Ang3(BYTE2RAD(angleX), BYTE2RAD(angleY), BYTE2RAD(angle)));
  84.  
  85.                 if (group.GetAlignToTerrainAmount() != 0.f)
  86.                 {
  87.                         Matrix33 m33;
  88.                         GetTerrain()->GetTerrainAlignmentMatrix(vPos, group.GetAlignToTerrainAmount(), m33);
  89.                         sample.q = Quat(m33) * Quat(mr);
  90.                 }
  91.                 else
  92.                 {
  93.                         sample.q = Quat(mr);
  94.                 }
  95.                 sample.q.NormalizeSafe();
  96.                 renderNode = m_pMergedMeshesManager->AddInstance(sample);
  97.         }
  98.  
  99.         return renderNode;
  100. }
  101.  
  102. void CTerrain::RemoveAllStaticObjects(int nSID)
  103. {
  104. #ifdef SEG_WORLD
  105.         if (nSID < 0)
  106.         {
  107.                 for (nSID = 0; nSID < Get3DEngine()->m_pObjectsTree.Count(); ++nSID)
  108.                         RemoveAllStaticObjects(nSID);
  109.                 return;
  110.         }
  111. #endif
  112.  
  113.         if (!Get3DEngine()->m_pObjectsTree[nSID] || nSID >= Get3DEngine()->m_pObjectsTree.Count())
  114.                 return;
  115.  
  116.         PodArray<SRNInfo> lstObjects;
  117.         Get3DEngine()->m_pObjectsTree[nSID]->MoveObjectsIntoList(&lstObjects, NULL);
  118.  
  119.         for (int i = 0; i < lstObjects.Count(); i++)
  120.         {
  121.                 IRenderNode* pNode = lstObjects.GetAt(i).pNode;
  122.                 switch (pNode->GetRenderNodeType())
  123.                 {
  124.                 case eERType_Vegetation:
  125.                         if (!(pNode->GetRndFlags() & ERF_PROCEDURAL))
  126.                                 pNode->ReleaseNode();
  127.                         break;
  128.                 case eERType_MergedMesh:
  129.                         pNode->ReleaseNode();
  130.                         break;
  131.                 }
  132.         }
  133. }
  134.  
  135. #define GET_Z_VAL(_x, _y) pTerrainBlock[(_x) * nTerrainSize + (_y)]
  136.  
  137. void CTerrain::BuildErrorsTableForArea(float* pLodErrors, int nMaxLods,
  138.                                        int X1, int Y1, int X2, int Y2, float* pTerrainBlock,
  139.                                        uint8* pSurfaceData, int nSurfOffsetX, int nSurfOffsetY,
  140.                                        int nSurfSizeX, int nSurfSizeY, bool& bHasHoleEdges)
  141. {
  142.         memset(pLodErrors, 0, nMaxLods * sizeof(pLodErrors[0]));
  143.         int nSectorSize = CTerrain::GetSectorSize() / CTerrain::GetHeightMapUnitSize();
  144.         int nTerrainSize = CTerrain::GetTerrainSize() / CTerrain::GetHeightMapUnitSize();
  145.  
  146.         bool bSectorHasHoles = false;
  147.         bool bSectorHasMesh = false;
  148.  
  149.         {
  150.                 int nLodUnitSize = 1;
  151.                 int x1 = max(0, X1 - nLodUnitSize);
  152.                 int x2 = min(nTerrainSize - nLodUnitSize, X2 + nLodUnitSize);
  153.                 int y1 = max(0, Y1 - nLodUnitSize);
  154.                 int y2 = min(nTerrainSize - nLodUnitSize, Y2 + nLodUnitSize);
  155.  
  156.                 for (int X = x1; X < x2; X += nLodUnitSize)
  157.                 {
  158.                         for (int Y = y1; Y < y2; Y += nLodUnitSize)
  159.                         {
  160.                                 int nSurfX = (X - nSurfOffsetX);
  161.                                 int nSurfY = (Y - nSurfOffsetY);
  162.                                 if (nSurfX >= 0 && nSurfY >= 0 && nSurfX < nSurfSizeX && nSurfY < nSurfSizeY && pSurfaceData)
  163.                                 {
  164.                                         int nSurfCell = nSurfX * nSurfSizeY + nSurfY;
  165.                                         assert(nSurfCell >= 0 && nSurfCell < nSurfSizeX * nSurfSizeY);
  166.                                         if (pSurfaceData[nSurfCell] == SRangeInfo::e_hole)
  167.                                                 bSectorHasHoles = true;
  168.                                         else
  169.                                                 bSectorHasMesh = true;
  170.                                 }
  171.                         }
  172.                 }
  173.         }
  174.  
  175.         bHasHoleEdges = (bSectorHasHoles && bSectorHasMesh);
  176.  
  177.         for (int nLod = 1; nLod < nMaxLods; nLod++)
  178.         {
  179.                 // calculate max difference between detail levels and actual height map
  180.                 float fMaxDiff = 0;
  181.  
  182.                 if (bHasHoleEdges)
  183.                         fMaxDiff = max(fMaxDiff, GetFloatCVar(e_TerrainLodRatioHolesMin));
  184.  
  185.                 int nLodUnitSize = (1 << nLod);
  186.  
  187.                 assert(nLodUnitSize <= nSectorSize);
  188.  
  189.                 int x1 = max(0, X1 - nLodUnitSize);
  190.                 int x2 = min(nTerrainSize - nLodUnitSize, X2 + nLodUnitSize);
  191.                 int y1 = max(0, Y1 - nLodUnitSize);
  192.                 int y2 = min(nTerrainSize - nLodUnitSize, Y2 + nLodUnitSize);
  193.  
  194.                 float fSurfSwitchError = 0.5f * nLod;
  195.  
  196.                 for (int X = x1; X < x2; X += nLodUnitSize)
  197.                 {
  198.                         for (int Y = y1; Y < y2; Y += nLodUnitSize)
  199.                         {
  200.                                 uint8 nLodedSurfType = 0;
  201.                                 {
  202.                                         int nSurfX = (X - nSurfOffsetX);
  203.                                         int nSurfY = (Y - nSurfOffsetY);
  204.                                         if (nSurfX >= 0 && nSurfY >= 0 && nSurfX < nSurfSizeX && nSurfY < nSurfSizeY && pSurfaceData)
  205.                                         {
  206.                                                 int nSurfCell = nSurfX * nSurfSizeY + nSurfY;
  207.                                                 assert(nSurfCell >= 0 && nSurfCell < nSurfSizeX * nSurfSizeY);
  208.                                                 nLodedSurfType = pSurfaceData[nSurfCell];
  209.                                         }
  210.                                 }
  211.  
  212.                                 for (int x = 1; x < nLodUnitSize; x++)
  213.                                 {
  214.                                         float kx = (float)x / (float)nLodUnitSize;
  215.  
  216.                                         float z1 = (1.f - kx) * GET_Z_VAL(X + 0, Y + 0) + (kx) * GET_Z_VAL(X + nLodUnitSize, Y + 0);
  217.                                         float z2 = (1.f - kx) * GET_Z_VAL(X + 0, Y + nLodUnitSize) + (kx) * GET_Z_VAL(X + nLodUnitSize, Y + nLodUnitSize);
  218.  
  219.                                         for (int y = 1; y < nLodUnitSize; y++)
  220.                                         {
  221.                                                 // skip map borders
  222.                                                 int nBorder = (nSectorSize >> 2);
  223.                                                 if ((X + x) < nBorder || (X + x) > (nTerrainSize - nBorder) ||
  224.                                                     (Y + y) < nBorder || (Y + y) > (nTerrainSize - nBorder))
  225.                                                         continue;
  226.  
  227.                                                 float ky = (float)y / nLodUnitSize;
  228.                                                 float fInterpolatedZ = (1.f - ky) * z1 + ky * z2;
  229.                                                 float fRealZ = GET_Z_VAL(X + x, Y + y);
  230.                                                 float fDiff = fabs(fRealZ - fInterpolatedZ);
  231.  
  232.                                                 if (fMaxDiff < fSurfSwitchError)
  233.                                                 {
  234.                                                         int nSurfX = (X + x - nSurfOffsetX);
  235.                                                         int nSurfY = (Y + y - nSurfOffsetY);
  236.                                                         if (nSurfX >= 0 && nSurfY >= 0 && nSurfX < nSurfSizeX && nSurfY < nSurfSizeY && pSurfaceData)
  237.                                                         {
  238.                                                                 int nSurfCell = nSurfX * nSurfSizeY + nSurfY;
  239.                                                                 assert(nSurfCell >= 0 && nSurfCell < nSurfSizeX * nSurfSizeY);
  240.                                                                 uint8 nRealSurfType = pSurfaceData[nSurfCell];
  241.  
  242.                                                                 // rise error if surface types will pop
  243.                                                                 if (nRealSurfType != nLodedSurfType)
  244.                                                                         fDiff = max(fDiff, fSurfSwitchError);
  245.                                                         }
  246.                                                 }
  247.  
  248.                                                 if (fDiff > fMaxDiff)
  249.                                                         fMaxDiff = fDiff;
  250.                                         }
  251.                                 }
  252.                         }
  253.                 }
  254.                 // note: values in m_arrGeomErrors table may be non incremental - this is correct
  255.                 pLodErrors[nLod] = fMaxDiff;
  256.         }
  257. }
  258.  
  259. void CTerrain::HighlightTerrain(int x1, int y1, int x2, int y2, int nSID)
  260. {
  261.         // Input dimensions are in units.
  262.         int iHMUnit = GetHeightMapUnitSize();
  263.         float x1u = (float)x1 * iHMUnit, x2u = (float)x2 * iHMUnit;
  264.         float y1u = (float)y1 * iHMUnit, y2u = (float)y2 * iHMUnit;
  265.  
  266.         ColorB clrRed(255, 0, 0);
  267.         IRenderAuxGeom* prag = GetISystem()->GetIRenderer()->GetIRenderAuxGeom();
  268.  
  269.         for (int x = x1; x < x2; x += 1)
  270.         {
  271.                 float xu = (float)x * iHMUnit;
  272.                 prag->DrawLine(Vec3(y1u, xu, GetZfromUnits(y1, x, nSID) + 0.5f), clrRed, Vec3(y1u, xu + iHMUnit, GetZfromUnits(y1, x + 1, nSID) + 0.5f), clrRed, 5.0f);
  273.                 prag->DrawLine(Vec3(y2u, xu, GetZfromUnits(y2, x, nSID) + 0.5f), clrRed, Vec3(y2u, xu + iHMUnit, GetZfromUnits(y2, x + 1, nSID) + 0.5f), clrRed, 5.0f);
  274.         }
  275.         for (int y = y1; y < y2; y += 1)
  276.         {
  277.                 float yu = (float)y * iHMUnit;
  278.                 prag->DrawLine(Vec3(yu, x1u, GetZfromUnits(y, x1, nSID) + 0.5f), clrRed, Vec3(yu + iHMUnit, x1u, GetZfromUnits(y + 1, x1, nSID) + 0.5f), clrRed, 5.0f);
  279.                 prag->DrawLine(Vec3(yu, x2u, GetZfromUnits(y, x2, nSID) + 0.5f), clrRed, Vec3(yu + iHMUnit, x2u, GetZfromUnits(y + 1, x2, nSID) + 0.5f), clrRed, 5.0f);
  280.         }
  281. }
  282.  
  283. void CTerrain::SetTerrainElevation(int X1, int Y1, int nSizeX, int nSizeY, float* pTerrainBlock,
  284.         unsigned char* pSurfaceData, int nSurfOrgX, int nSurfOrgY, int nSurfSizeX, int nSurfSizeY,
  285.         uint32* pResolMap, int nResolMapSizeX, int nResolMapSizeY, int nSID)
  286. {
  287. #ifndef _RELEASE
  288.  
  289.         //LOADING_TIME_PROFILE_SECTION;
  290.         FUNCTION_PROFILER_3DENGINE;
  291.  
  292.         float fStartTime = GetCurAsyncTimeSec();
  293.         int nUnitSize = CTerrain::GetHeightMapUnitSize();
  294.         int nHmapSize = CTerrain::GetTerrainSize() / nUnitSize;
  295.  
  296.         ResetHeightMapCache();
  297.  
  298.         // everything is in units in this function
  299.  
  300.         assert(nSizeX == nSizeY);
  301.         assert(X1 == ((X1 >> m_nUnitsToSectorBitShift) << m_nUnitsToSectorBitShift));
  302.         assert(Y1 == ((Y1 >> m_nUnitsToSectorBitShift) << m_nUnitsToSectorBitShift));
  303.         assert(nSizeX == ((nSizeX >> m_nUnitsToSectorBitShift) << m_nUnitsToSectorBitShift));
  304.         assert(nSizeY == ((nSizeY >> m_nUnitsToSectorBitShift) << m_nUnitsToSectorBitShift));
  305.  
  306.         if (X1 < 0 || Y1 < 0 || X1 + nSizeX > nHmapSize || Y1 + nSizeY > nHmapSize)
  307.         {
  308.                 Warning("CTerrain::SetTerrainHeightMapBlock: (X1,Y1) values out of range");
  309.                 return;
  310.         }
  311.  
  312. #ifdef SEG_WORLD
  313.         if (nSID < 0)
  314.         {
  315.                 int X2 = X1 + nSizeX;
  316.                 int Y2 = Y1 + nSizeY;
  317.                 int nEndSID = GetMaxSegmentsCount();
  318.                 for (nSID = 0; nSID < nEndSID; ++nSID)
  319.                 {
  320.                         AABB aabb;
  321.                         if (!GetSegmentBounds(nSID, aabb))
  322.                                 continue;
  323.                         int sx1 = ((int)aabb.min.x) >> m_nBitShift;
  324.                         int sy1 = ((int)aabb.min.y) >> m_nBitShift;
  325.                         int sx2 = ((int)aabb.max.x) >> m_nBitShift;
  326.                         int sy2 = ((int)aabb.max.y) >> m_nBitShift;
  327.  
  328.                         int xMin = max(X1, sx1);
  329.                         int xMax = min(X2, sx2);
  330.                         if (xMin >= xMax)
  331.                                 continue;
  332.                         int yMin = max(Y1, sy1);
  333.                         int yMax = min(Y2, sy2);
  334.                         if (yMin >= yMax)
  335.                                 continue;
  336.                         SetTerrainElevation(xMin - sx1, yMin - sy1, xMax - xMin, yMax - yMin,
  337.                                 pTerrainBlock, pSurfaceData, nSurfOrgX, nSurfOrgY, nSurfSizeX, nSurfSizeY,
  338.                                 pResolMap, nResolMapSizeX, nResolMapSizeY, nSID);
  339.                 }
  340.                 return;
  341.         }
  342. #endif
  343.  
  344.         AABB aabb;
  345.         if (!GetSegmentBounds(nSID, aabb))
  346.         {
  347.                 Warning("CTerrain::SetTerrainElevation: invalid segment id specified!");
  348.                 return;
  349.         }
  350.         int x0 = ((int)aabb.min.x) >> m_nBitShift;
  351.         int y0 = ((int)aabb.min.y) >> m_nBitShift;
  352.  
  353.         if (!GetParentNode(nSID))
  354.                 BuildSectorsTree(false, nSID);
  355.  
  356.         Array2d<struct CTerrainNode*>& sectorLayer = m_arrSecInfoPyramid[nSID][0];
  357.  
  358.         int rangeX1 = max(0, X1 >> m_nUnitsToSectorBitShift);
  359.         int rangeY1 = max(0, Y1 >> m_nUnitsToSectorBitShift);
  360.         int rangeX2 = min(sectorLayer.GetSize(), (X1 + nSizeX) >> m_nUnitsToSectorBitShift);
  361.         int rangeY2 = min(sectorLayer.GetSize(), (Y1 + nSizeY) >> m_nUnitsToSectorBitShift);
  362.  
  363.         std::vector<float> rawHeightmap;
  364.  
  365.         AABB modifiedArea;
  366.         modifiedArea.Reset();
  367.  
  368.         for (int rangeX = rangeX1; rangeX < rangeX2; rangeX++)
  369.         {
  370.                 for (int rangeY = rangeY1; rangeY < rangeY2; rangeY++)
  371.                 {
  372.                         CTerrainNode* pTerrainNode = sectorLayer[rangeX][rangeY];
  373.  
  374.                         int x1 = x0 + (rangeX << m_nUnitsToSectorBitShift);
  375.                         int y1 = y0 + (rangeY << m_nUnitsToSectorBitShift);
  376.                         int x2 = x0 + ((rangeX + 1) << m_nUnitsToSectorBitShift);
  377.                         int y2 = y0 + ((rangeY + 1) << m_nUnitsToSectorBitShift);
  378.  
  379.                         // find min/max
  380.                         float fMin = pTerrainBlock[x1 * nHmapSize + y1];
  381.                         float fMax = fMin;
  382.  
  383.                         for (int x = x1; x <= x2; x++)
  384.                         {
  385.                                 for (int y = y1; y <= y2; y++)
  386.                                 {
  387.                                         float fHeight = pTerrainBlock[CLAMP(x, 0, nHmapSize - 1) * nHmapSize + CLAMP(y, 0, nHmapSize - 1)];
  388.  
  389.                                         if (fHeight > fMax) fMax = fHeight;
  390.                                         if (fHeight < fMin) fMin = fHeight;
  391.                                 }
  392.                         }
  393.  
  394.                         // reserve some space for in-game deformations
  395.                         fMin = max(0.f, fMin - TERRAIN_DEFORMATION_MAX_DEPTH);
  396.  
  397.                         float fMaxTexelSizeMeters = -1;
  398.  
  399.                         if (pResolMap)
  400.                         {
  401.                                 // get max allowed texture resolution here
  402.                                 int nResMapX = (nResolMapSizeX * (x1 / 2 + x2 / 2) / nHmapSize);
  403.                                 int nResMapY = (nResolMapSizeY * (y1 / 2 + y2 / 2) / nHmapSize);
  404.                                 nResMapX = CLAMP(nResMapX, 0, nResolMapSizeX - 1);
  405.                                 nResMapY = CLAMP(nResMapY, 0, nResolMapSizeY - 1);
  406.                                 int nTexRes = pResolMap[nResMapY + nResMapX * nResolMapSizeY];
  407.                                 int nResTileSizeMeters = GetTerrainSize() / nResolMapSizeX;
  408.                                 fMaxTexelSizeMeters = (float)nResTileSizeMeters / (float)nTexRes;
  409.                         }
  410.  
  411.                         // find error metrics
  412.                         if (!pTerrainNode->m_pGeomErrors)
  413.                                 pTerrainNode->m_pGeomErrors = new float[m_nUnitsToSectorBitShift];
  414.  
  415.                         bool bHasHoleEdges = false;
  416.  
  417.                         {
  418.                                 BuildErrorsTableForArea(pTerrainNode->m_pGeomErrors, m_nUnitsToSectorBitShift, x1, y1, x2, y2, pTerrainBlock, pSurfaceData, nSurfOrgX, nSurfOrgY, nSurfSizeX, nSurfSizeY, bHasHoleEdges);
  419.                         }
  420.  
  421.                         assert(pTerrainNode->m_pGeomErrors[0] == 0);
  422.  
  423.                         pTerrainNode->m_boxHeigtmapLocal.min.Set((float)((x1 - x0) * nUnitSize), (float)((y1 - y0) * nUnitSize), fMin);
  424.                         pTerrainNode->m_boxHeigtmapLocal.max.Set((float)((x2 - x0) * nUnitSize), (float)((y2 - y0) * nUnitSize), max(fMax, GetWaterLevel()));
  425.  
  426.                         // same as in SetLOD()
  427.                         float fAllowedError = 0.05f; // ( GetCVars()->e_TerrainLodRatio * 32.f ) / 180.f * 2.5f;
  428.                         int nGeomMML = m_nUnitsToSectorBitShift - 1;
  429.  
  430.                         for (; nGeomMML > 0; nGeomMML--)
  431.                         {
  432.                                 float fStepMeters = (float)((1 << nGeomMML) * GetHeightMapUnitSize());
  433.  
  434.                                 if (fStepMeters <= fMaxTexelSizeMeters)
  435.                                         break;
  436.  
  437.                                 if (pTerrainNode->m_pGeomErrors[nGeomMML] < fAllowedError)
  438.                                         break;
  439.                         }
  440.  
  441.                         if (nGeomMML == m_nUnitsToSectorBitShift - 1 && (fMax - fMin) < 0.05f)
  442.                                 nGeomMML = m_nUnitsToSectorBitShift;
  443.  
  444.                         if (bHasHoleEdges)
  445.                                 nGeomMML = 0;
  446.  
  447.                         SRangeInfo& ri = pTerrainNode->m_rangeInfo;
  448.  
  449.                         // TODO: add proper fp16/fp32 support
  450.                         /*
  451.                                         ri.fOffset = fMin = CryConvertHalfToFloat(CryConvertFloatToHalf(fMin));
  452.                                         ri.fRange = powf(2.0f, ceilf(logf((fMax - fMin) / 65535.f)/logf(2.0f)));
  453.                          */
  454.                          /*             ri.fOffset = fMin;
  455.                                          ri.fRange       = (fMax - fMin) / 65535.f;
  456.                                 */
  457.  
  458.                         int nStep = 1 << nGeomMML;
  459.                         int nMaxStep = 1 << m_nUnitsToSectorBitShift;
  460.  
  461.                         if (ri.nSize != nMaxStep / nStep + 1)
  462.                         {
  463.                                 delete[] ri.pHMData;
  464.                                 ri.nSize = nMaxStep / nStep + 1;
  465.                                 ri.pHMData = new uint16[ri.nSize * ri.nSize];
  466.                                 ri.UpdateBitShift(m_nUnitsToSectorBitShift);
  467.                         }
  468.  
  469.                         if (rawHeightmap.size() < (size_t)ri.nSize * ri.nSize)
  470.                         {
  471.                                 rawHeightmap.resize(ri.nSize * ri.nSize);
  472.                         }
  473.  
  474.                         {
  475.                                 int ix = CLAMP(x1, 1, nHmapSize - 1);
  476.                                 int iy = CLAMP(y1, 1, nHmapSize - 1);
  477.  
  478.                                 fMin = pTerrainBlock[ix * nHmapSize + iy];
  479.                                 fMax = fMin;
  480.                         }
  481.  
  482.                         // fill height map data array in terrain node, all in units
  483.                         for (int x = x1; x <= x2; x += nStep)
  484.                         {
  485.                                 for (int y = y1; y <= y2; y += nStep)
  486.                                 {
  487.                                         int ix = min(nHmapSize - 1, x);
  488.                                         int iy = min(nHmapSize - 1, y);
  489.  
  490.                                         float fHeight = pTerrainBlock[ix * nHmapSize + iy];
  491.  
  492.                                         if (fHeight > fMax) fMax = fHeight;
  493.                                         if (fHeight < fMin) fMin = fHeight;
  494.  
  495.                                         // TODO: add proper fp16/fp32 support
  496.  
  497.                                         int x_local = (x - x1) / nStep;
  498.                                         int y_local = (y - y1) / nStep;
  499.  
  500.                                         rawHeightmap[x_local * ri.nSize + y_local] = fHeight;
  501.                                 }
  502.                         }
  503.  
  504.                         ri.fOffset = fMin;
  505.                         ri.fRange = (fMax - fMin) / float(0xFFF0);
  506.  
  507.                         const unsigned mask12bit = (1 << 12) - 1;
  508.                         const int inv5cm = 20;
  509.  
  510.                         int iOffset = int(fMin * inv5cm);
  511.                         int iRange = int((fMax - fMin) * inv5cm);
  512.                         int iStep = iRange ? (iRange + mask12bit - 1) / mask12bit : 1;
  513.  
  514.                         iRange /= iStep;
  515.  
  516.                         ri.iOffset = iOffset;
  517.                         ri.iRange = iRange;
  518.                         ri.iStep = iStep;
  519.  
  520.                         bool bHMDataIsModified = false;
  521.  
  522.                         for (int x = x1; x <= x2; x += nStep)
  523.                         {
  524.                                 for (int y = y1; y <= y2; y += nStep)
  525.                                 {
  526.                                         int xlocal = (x - x1) / nStep;
  527.                                         int ylocal = (y - y1) / nStep;
  528.                                         int nCellLocal = xlocal * ri.nSize + ylocal;
  529.  
  530.                                         unsigned hdec = int((rawHeightmap[nCellLocal] - fMin) * inv5cm) / iStep;
  531.  
  532.                                         uint16 usSurfType = ri.GetSurfaceTypeByIndex(nCellLocal); // BAD CODE!!! we deleted this info and new(ed) it => invalid data here
  533.  
  534.                                         assert(x >= x0 + X1 && y >= y0 + Y1 && x <= x0 + X1 + nSurfSizeX && y <= y0 + Y1 + nSurfSizeY && pSurfaceData);
  535.  
  536.                                         int nSurfX = (x - nSurfOrgX);
  537.                                         int nSurfY = (y - nSurfOrgY);
  538.  
  539.                                         if (nSurfX >= 0 && nSurfY >= 0 && nSurfX < nSurfSizeX && nSurfY < nSurfSizeY && pSurfaceData)
  540.                                         {
  541.                                                 int nSurfCell = nSurfX * nSurfSizeY + nSurfY;
  542.                                                 assert(nSurfCell >= 0 && nSurfCell < nSurfSizeX * nSurfSizeY);
  543.                                                 usSurfType = ri.GetLocalSurfaceTypeID(pSurfaceData[nSurfCell]);
  544.                                         }
  545.  
  546.                                         uint16 nNewValue = (usSurfType& SRangeInfo::e_index_hole) | (hdec << 4);
  547.  
  548.                                         if (nNewValue != ri.pHMData[nCellLocal])
  549.                                         {
  550.                                                 ri.pHMData[nCellLocal] = nNewValue;
  551.  
  552.                                                 bHMDataIsModified = true;
  553.                                         }
  554.                                 }
  555.                         }
  556.  
  557.                         // re-init surface types info and update vert buffers in entire brunch
  558.                         if (GetParentNode(nSID))
  559.                         {
  560.                                 CTerrainNode* pNode = pTerrainNode;
  561.                                 while (pNode)
  562.                                 {
  563.                                         pNode->ReleaseHeightMapGeometry();
  564.                                         pNode->RemoveProcObjects(false, false);
  565.                                         pNode->UpdateDetailLayersInfo(false);
  566.  
  567.                                         // propagate bounding boxes and error metrics to parents
  568.                                         if (pNode != pTerrainNode)
  569.                                         {
  570.                                                 for (int i = 0; i < m_nUnitsToSectorBitShift; i++)
  571.                                                 {
  572.                                                         pNode->m_pGeomErrors[i] = max(max(
  573.                                                                 pNode->m_pChilds[0].m_pGeomErrors[i],
  574.                                                                 pNode->m_pChilds[1].m_pGeomErrors[i]), max(
  575.                                                                         pNode->m_pChilds[2].m_pGeomErrors[i],
  576.                                                                         pNode->m_pChilds[3].m_pGeomErrors[i]));
  577.                                                 }
  578.  
  579.                                                 pNode->m_boxHeigtmapLocal.min = SetMaxBB();
  580.                                                 pNode->m_boxHeigtmapLocal.max = SetMinBB();
  581.  
  582.                                                 for (int nChild = 0; nChild < 4; nChild++)
  583.                                                 {
  584.                                                         pNode->m_boxHeigtmapLocal.min.CheckMin(pNode->m_pChilds[nChild].m_boxHeigtmapLocal.min);
  585.                                                         pNode->m_boxHeigtmapLocal.max.CheckMax(pNode->m_pChilds[nChild].m_boxHeigtmapLocal.max);
  586.                                                 }
  587.                                         }
  588.  
  589.                                         // request elevation texture update
  590.                                         if (pNode->m_nNodeTexSet.nSlot0 != 0xffff && pNode->m_nNodeTexSet.nSlot0 < m_pTerrain->m_texCache[2].GetPoolSize())
  591.                                         {
  592.                                                 if(bHMDataIsModified)
  593.                                                         pNode->m_eElevTexEditingState = eTES_SectorIsModified_AtlasIsDirty;
  594.                                         }
  595.  
  596.                                         pNode = pNode->m_pParent;
  597.                                 }
  598.                         }
  599.  
  600.                         modifiedArea.Add(pTerrainNode->GetBBox());
  601.                 }
  602.         }
  603.  
  604.         if (GetCurAsyncTimeSec() - fStartTime > 1)
  605.                 PrintMessage("CTerrain::SetTerrainElevation took %.2f sec", GetCurAsyncTimeSec() - fStartTime);
  606.  
  607.         if (Get3DEngine()->m_pObjectsTree[nSID])
  608.                 Get3DEngine()->m_pObjectsTree[nSID]->UpdateTerrainNodes();
  609.  
  610.         // update roads
  611.         if (Get3DEngine()->m_pObjectsTree[nSID] && (GetCVars()->e_TerrainDeformations || m_bEditor))
  612.         {
  613.                 PodArray<IRenderNode*> lstRoads;
  614.  
  615.                 aabb = AABB(
  616.                   Vec3((float)(x0 + X1) * (float)nUnitSize, (float)(y0 + Y1) * (float)nUnitSize, 0.f),
  617.                   Vec3((float)(x0 + X1) * (float)nUnitSize + (float)nSizeX * (float)nUnitSize, (float)(y0 + Y1) * (float)nUnitSize + (float)nSizeY * (float)nUnitSize, 1024.f));
  618.  
  619.                 Get3DEngine()->m_pObjectsTree[nSID]->GetObjectsByType(lstRoads, eERType_Road, &aabb);
  620.                 for (int i = 0; i < lstRoads.Count(); i++)
  621.                 {
  622.                         CRoadRenderNode* pRoad = (CRoadRenderNode*)lstRoads[i];
  623.                         pRoad->OnTerrainChanged();
  624.                 }
  625.         }
  626.  
  627.         if (GetParentNode(nSID))
  628.                 GetParentNode(nSID)->UpdateRangeInfoShift();
  629.  
  630.         if (!modifiedArea.IsReset())
  631.         {
  632.                 modifiedArea.Expand(Vec3(2.f * GetHeightMapUnitSize()));
  633.                 ResetTerrainVertBuffers(&modifiedArea, 0);
  634.         }
  635.  
  636.         m_bHeightMapModified = 0;
  637.  
  638. #endif // _RELEASE
  639. }
  640.  
  641. void CTerrain::SetTerrainSectorTexture(int nTexSectorX, int nTexSectorY, unsigned int textureId, bool bMergeNotAllowed, int nSID)
  642. {
  643. #ifdef SEG_WORLD
  644.         nSID = WorldToSegment(nTexSectorX, nTexSectorY, m_nBitShift + m_nUnitsToSectorBitShift, nSID);
  645.         if (nSID < 0)
  646.         {
  647.                 Warning("CTerrain::LockSectorTexture: (nTexSectorX, nTexSectorY) values out of range");
  648.                 return;
  649.         }
  650. #endif
  651.         int nDiffTexTreeLevelOffset = 0;
  652.  
  653.         if (nTexSectorX < 0 ||
  654.             nTexSectorY < 0 ||
  655.             nTexSectorX >= CTerrain::GetSectorsTableSize(nSID) >> nDiffTexTreeLevelOffset ||
  656.             nTexSectorY >= CTerrain::GetSectorsTableSize(nSID) >> nDiffTexTreeLevelOffset)
  657.         {
  658.                 Warning("CTerrain::LockSectorTexture: (nTexSectorX, nTexSectorY) values out of range");
  659.                 return;
  660.         }
  661.  
  662. #ifdef SEG_WORLD
  663.         if (!GetParentNode(nSID))
  664.                 BuildSectorsTree(false, nSID);
  665.  
  666.         // open terrain texture now, otherwise it will be opened later and unlock all sectors
  667.         if (Get3DEngine()->IsSegmentOperationInProgress() && !m_arrBaseTexInfos[nSID].m_nDiffTexIndexTableSize)
  668.                 OpenTerrainTextureFile(m_arrBaseTexInfos[nSID].m_hdrDiffTexHdr, m_arrBaseTexInfos[nSID].m_hdrDiffTexInfo,
  669.                                        m_arrSegmentPaths[nSID] + COMPILED_TERRAIN_TEXTURE_FILE_NAME, m_arrBaseTexInfos[nSID].m_ucpDiffTexTmpBuffer, m_arrBaseTexInfos[nSID].m_nDiffTexIndexTableSize, nSID);
  670. #endif
  671.  
  672.         CTerrainNode* pNode = m_arrSecInfoPyramid[nSID][nDiffTexTreeLevelOffset][nTexSectorX][nTexSectorY];
  673.  
  674. #ifdef SEG_WORLD
  675.         if (!idOld == !textureId || textureId == (unsigned int)-1)
  676.                 return;
  677. #endif
  678.  
  679.         while (pNode)
  680.         {
  681.                 pNode->EnableTextureEditingMode(textureId);
  682.                 pNode = pNode->m_pParent;
  683.         }
  684. }
  685.  
  686. void CTerrain::ResetTerrainVertBuffers(const AABB* pBox, int nSID)
  687. {
  688.         if (nSID == -1)
  689.         {
  690.                 for (int id = 0; id < m_pParentNodes.Count(); id++)
  691.                 {
  692.                         if (Get3DEngine()->IsSegmentSafeToUse(id) && GetParentNode(id))
  693.                                 GetParentNode(id)->ReleaseHeightMapGeometry(true, pBox);
  694.                 }
  695.         }
  696.         else if (GetParentNode(nSID))
  697.                 GetParentNode(nSID)->ReleaseHeightMapGeometry(true, pBox);
  698. }
  699.  
  700. void CTerrain::SetOceanWaterLevel(float fOceanWaterLevel)
  701. {
  702.         SetWaterLevel(fOceanWaterLevel);
  703.         pe_params_buoyancy pb;
  704.         pb.waterPlane.origin.Set(0, 0, fOceanWaterLevel);
  705.         if (gEnv->pPhysicalWorld)
  706.                 gEnv->pPhysicalWorld->AddGlobalArea()->SetParams(&pb);
  707.         extern float g_oceanStep;
  708.         g_oceanStep = -1; // if e_PhysOceanCell is used, make it re-apply the params on Update
  709. }
  710.  
  711. bool CTerrain::CanPaintSurfaceType(int x, int y, int r, uint16 usGlobalSurfaceType)
  712. {
  713.         // Checks if the palettes of all sectors touching the given brush square can accept usGlobalSurfaceType.
  714.  
  715.         if (usGlobalSurfaceType == SRangeInfo::e_hole)
  716.                 return true;
  717.  
  718.         int nTerrainSizeSectors = CTerrain::GetTerrainSize() / CTerrain::GetSectorSize();
  719.  
  720.         int rangeX1 = max(0, (x - r) >> m_nUnitsToSectorBitShift);
  721.         int rangeY1 = max(0, (y - r) >> m_nUnitsToSectorBitShift);
  722.         int rangeX2 = min(nTerrainSizeSectors, ((x + r) >> m_nUnitsToSectorBitShift) + 1);
  723.         int rangeY2 = min(nTerrainSizeSectors, ((y + r) >> m_nUnitsToSectorBitShift) + 1);
  724.  
  725.         // Can we fit this surface type into the palettes of all sectors involved?
  726.         for (int rangeX = rangeX1; rangeX < rangeX2; rangeX++)
  727.                 for (int rangeY = rangeY1; rangeY < rangeY2; rangeY++)
  728.                 {
  729.                         int rx = rangeX, ry = rangeY;
  730.                         int nSID = WorldToSegment(ry, rx, m_nBitShift + m_nUnitsToSectorBitShift);
  731.                         if (nSID < 0)
  732.                                 continue;
  733.  
  734.                         Array2d<struct CTerrainNode*>& sectorLayer = m_arrSecInfoPyramid[nSID][0];
  735.                         CTerrainNode* pTerrainNode = sectorLayer[ry][rx];
  736.                         SRangeInfo& ri = pTerrainNode->m_rangeInfo;
  737.  
  738.                         if (ri.GetLocalSurfaceTypeID(usGlobalSurfaceType) == SRangeInfo::e_index_hole)
  739.                         {
  740.                                 IRenderAuxText::DrawLabel(Vec3((float)y, (float)x, GetZfromUnits(y, x, -1) + 1.0f), 2.0f, "SECTOR PALETTE FULL!");
  741.                                 HighlightTerrain(
  742.                                   rangeX << m_nUnitsToSectorBitShift, rangeY << m_nUnitsToSectorBitShift,
  743.                                   (rangeX + 1) << m_nUnitsToSectorBitShift, (rangeY + 1) << m_nUnitsToSectorBitShift);
  744.                                 return false;
  745.                         }
  746.                 }
  747.  
  748.         return true;
  749. }
  750.  
  751. ILINE bool CTerrain::IsRenderNodeIncluded(IRenderNode* pNode, const AABB& region, const uint16* pIncludeLayers, int numIncludeLayers)
  752. {
  753.         EERType type = pNode->GetRenderNodeType();
  754.  
  755.         switch (type)
  756.         {
  757.         case eERType_Brush:
  758.         case eERType_Vegetation:
  759.         case eERType_Decal:
  760.         case eERType_WaterVolume:
  761.         case eERType_MergedMesh:
  762.                 break;
  763.  
  764.         default:
  765.                 CRY_ASSERT_TRACE(0, ("Need to support cloning terrain object type %d", type));
  766.                 return false;
  767.         }
  768.  
  769.         if (type == eERType_MergedMesh)
  770.         {
  771.                 CMergedMeshRenderNode* pMergedMesh = (CMergedMeshRenderNode*)pNode;
  772.  
  773.                 // The bounding box for a merged mesh can slop over into a neighboring grid
  774.                 // chunk, so only clone it if the center is contained in the region we're cloning.
  775.                 if (!region.IsContainPoint(pMergedMesh->m_pos))
  776.                         return false;
  777.         }
  778.  
  779.         if (numIncludeLayers == 0)
  780.                 return true;
  781.  
  782.         const uint16 layerId = pNode->GetLayerId();
  783.  
  784.         // Some terrain objects don't have layer ids (like vegetation), so we have to include
  785.         // them even if we're filtering.
  786.         if (layerId == 0)
  787.         {
  788.                 return true;
  789.         }
  790.         else
  791.         {
  792.                 for (int e = 0; e < numIncludeLayers; e++)
  793.                 {
  794.                         if (pIncludeLayers[e] == layerId)
  795.                         {
  796.                                 return true;
  797.                         }
  798.                 }
  799.         }
  800.  
  801.         // If we made it to this point none of the include layers matched, so it's not excluded
  802.         return false;
  803. }
  804.  
  805. void CTerrain::MarkAndOffsetCloneRegion(const AABB& region, const Vec3& offset)
  806. {
  807.         C3DEngine* p3DEngine = Get3DEngine();
  808.         int numObjects = p3DEngine->GetObjectsInBox(region, NULL);
  809.  
  810.         if (numObjects == 0)
  811.                 return;
  812.  
  813.         PodArray<IRenderNode*> objects;
  814.         objects.resize(numObjects);
  815.         p3DEngine->GetObjectsInBox(region, &objects[0]);
  816.  
  817.         int skyLayer = gEnv->pEntitySystem->GetLayerId("Sky");
  818.  
  819.         for (int i = 0; i < numObjects; i++)
  820.         {
  821.                 IRenderNode* pNode = objects[i];
  822.                 EERType type = pNode->GetRenderNodeType();
  823.  
  824.                 // HACK: Need a way for certain layers to not get offset, like the skybox
  825.                 if (type == eERType_Brush && skyLayer != -1)
  826.                 {
  827.                         CBrush* pBrush = (CBrush*)pNode;
  828.                         if (pBrush->GetLayerId() == skyLayer)
  829.                                 continue;
  830.                 }
  831.  
  832.                 if (IsRenderNodeIncluded(pNode, region, NULL, 0))
  833.                 {
  834.                         CRY_ASSERT_MESSAGE((pNode->GetRndFlags() & ERF_CLONE_SOURCE) == 0, "Marking already marked node, is an object overlapping multiple regions?");
  835.  
  836.                         pNode->SetRndFlags(ERF_CLONE_SOURCE, true);
  837.  
  838.                         pNode->OffsetPosition(offset);
  839.                         p3DEngine->RegisterEntity(pNode);
  840.                 }
  841.         }
  842. }
  843.  
  844. void CTerrain::CloneRegion(const AABB& region, const Vec3& offset, float zRotation, const uint16* pIncludeLayers, int numIncludeLayers)
  845. {
  846.         C3DEngine* p3DEngine = Get3DEngine();
  847.         int numObjects = p3DEngine->GetObjectsInBox(region, NULL);
  848.  
  849.         if (numObjects == 0)
  850.                 return;
  851.  
  852.         PodArray<IRenderNode*> objects;
  853.         objects.resize(numObjects);
  854.         p3DEngine->GetObjectsInBox(region, &objects[0]);
  855.  
  856.         Vec3 localOrigin = region.GetCenter();
  857.         Matrix34 l2w(Matrix33::CreateRotationZ(zRotation));
  858.         l2w.SetTranslation(offset);
  859.  
  860.         for (int i = 0; i < numObjects; i++)
  861.         {
  862.                 IRenderNode* pNode = objects[i];
  863.  
  864.                 // If this wasn't flagged as a clone source, don't include it
  865.                 if ((pNode->GetRndFlags() & ERF_CLONE_SOURCE) == 0)
  866.                         continue;
  867.  
  868.                 if (!IsRenderNodeIncluded(pNode, region, pIncludeLayers, numIncludeLayers))
  869.                         continue;
  870.  
  871.                 IRenderNode* pNodeClone = NULL;
  872.  
  873.                 EERType type = pNode->GetRenderNodeType();
  874.                 if (type == eERType_Brush)
  875.                 {
  876.                         CBrush* pSrcBrush = (CBrush*)pNode;
  877.  
  878.                         pNodeClone = pSrcBrush->Clone();
  879.                         CBrush* pBrush = (CBrush*)pNodeClone;
  880.  
  881.                         pBrush->m_Matrix.SetTranslation(pBrush->m_Matrix.GetTranslation() - localOrigin);
  882.                         pBrush->m_Matrix = l2w * pBrush->m_Matrix;
  883.  
  884.                         pBrush->CalcBBox();
  885.  
  886.                         pBrush->m_pOcNode = NULL;
  887.  
  888.                         // to get correct indirect lighting the registration must be done before checking if this object is inside a VisArea
  889.                         Get3DEngine()->RegisterEntity(pBrush, 0);
  890.  
  891.                         //if (gEnv->IsEditorGameMode())
  892.                         {
  893.                                 //pBrush->Physicalize();
  894.                         }
  895.                         //else
  896.                         {
  897.                                 // keep everything deactivated, game will activate it later
  898.                                 //if(Get3DEngine()->IsAreaActivationInUse())
  899.                                 pBrush->SetRndFlags(ERF_HIDDEN, false);
  900.  
  901.                                 if (!(Get3DEngine()->IsAreaActivationInUse() && GetCVars()->e_ObjectLayersActivationPhysics == 1))// && !(pChunk->m_dwRndFlags&ERF_NO_PHYSICS))
  902.                                         pBrush->Physicalize();
  903.                         }
  904.                 }
  905.                 else if (type == eERType_Vegetation)
  906.                 {
  907.                         pNodeClone = pNode->Clone();
  908.                         CVegetation* pVeg = (CVegetation*)pNodeClone;
  909.  
  910.                         Matrix34 matrix;
  911.                         matrix.SetRotationZ(pVeg->GetZAngle(), pVeg->m_vPos - localOrigin);
  912.  
  913.                         matrix = l2w * matrix;
  914.  
  915.                         pVeg->m_vPos = matrix.GetTranslation();
  916.  
  917.                         // Vegetation stores rotation as a byte representing degrees, so we have to remap it back
  918.                         CryQuat rot(matrix);
  919.                         float zRot = rot.GetRotZ();
  920.                         pVeg->m_ucAngle = (byte)((RAD2DEG(zRot) / 360.0f) * 255.0f);
  921.  
  922.                         pVeg->CalcBBox();
  923.  
  924.                         pVeg->Physicalize();
  925.  
  926.                         Get3DEngine()->RegisterEntity(pVeg, 0);
  927.                 }
  928.                 else if (type == eERType_Decal)
  929.                 {
  930.                         pNodeClone = pNode->Clone();
  931.                         CDecalRenderNode* pDecal = (CDecalRenderNode*)pNodeClone;
  932.  
  933.                         Matrix34 mat = pDecal->GetMatrix();
  934.                         mat.SetTranslation(mat.GetTranslation() - localOrigin);
  935.                         mat = l2w * mat;
  936.  
  937.                         pDecal->SetMatrixFull(mat);
  938.  
  939.                         Get3DEngine()->RegisterEntity(pDecal);
  940.                         GetObjManager()->m_decalsToPrecreate.push_back(pDecal);
  941.                 }
  942.                 else if (type == eERType_WaterVolume)
  943.                 {
  944.                         pNodeClone = pNode->Clone();
  945.                         CWaterVolumeRenderNode* pWaterVol = (CWaterVolumeRenderNode*)pNodeClone;
  946.  
  947.                         pWaterVol->Transform(localOrigin, l2w);
  948.  
  949.                         pWaterVol->Physicalize();
  950.  
  951.                         Get3DEngine()->RegisterEntity(pWaterVol);
  952.                 }
  953.                 else if (type == eERType_MergedMesh)
  954.                 {
  955.                         CMergedMeshRenderNode* pSrcMergedMesh = (CMergedMeshRenderNode*)pNode;
  956.  
  957.                         // Transform the position of the source merged mesh to our destination location
  958.                         Vec3 dstPos;
  959.                         {
  960.                                 Matrix34 dst;
  961.                                 dst.SetTranslationMat(pSrcMergedMesh->m_pos - localOrigin);
  962.                                 dst = l2w * dst;
  963.                                 dstPos = dst.GetTranslation();
  964.                         }
  965.  
  966.                         // Get the merged mesh node for this coordinate.
  967.                         CMergedMeshRenderNode* pDstMergedMesh = m_pMergedMeshesManager->GetNode(dstPos);
  968.                         CRY_ASSERT_MESSAGE(pDstMergedMesh->m_pos == dstPos, "Cloned destination position isn't on grid");
  969.                         CRY_ASSERT_MESSAGE(pDstMergedMesh->m_nGroups == 0, "Cloning into a used chunk");
  970.  
  971.                         if (pDstMergedMesh->m_nGroups == 0)
  972.                         {
  973.                                 pDstMergedMesh->m_initPos = pSrcMergedMesh->m_initPos;
  974.                                 pDstMergedMesh->m_zRotation = zRotation;
  975.  
  976.                                 // Transform the AABB's
  977.                                 AABB visibleAABB = pSrcMergedMesh->m_visibleAABB;
  978.                                 visibleAABB.Move(-localOrigin);
  979.                                 visibleAABB.SetTransformedAABB(l2w, visibleAABB);
  980.                                 pDstMergedMesh->m_visibleAABB = visibleAABB;
  981.  
  982.                                 AABB internalAABB = pSrcMergedMesh->m_internalAABB;
  983.                                 internalAABB.Move(-localOrigin);
  984.                                 internalAABB.SetTransformedAABB(l2w, internalAABB);
  985.                                 pDstMergedMesh->m_internalAABB = internalAABB;
  986.  
  987.                                 pSrcMergedMesh->CopyIRenderNodeData(pDstMergedMesh);
  988.  
  989.                                 if (!gEnv->IsDedicated())
  990.                                 {
  991.                                         // In the editor the merged meshes have extra proxy data.  We don't
  992.                                         // clear out the source merged meshes in the editor, so the easiest
  993.                                         // solution is to just share the source groups and not delete them
  994.                                         // on destruction.
  995.                                         if (gEnv->IsEditorGameMode())
  996.                                         {
  997.                                                 pDstMergedMesh->m_ownsGroups = 0;
  998.                                                 pDstMergedMesh->m_groups = pSrcMergedMesh->m_groups;
  999.                                                 pDstMergedMesh->m_nGroups = pSrcMergedMesh->m_nGroups;
  1000.                                         }
  1001.                                         else
  1002.                                         {
  1003.                                                 for (size_t i = 0; i < pSrcMergedMesh->m_nGroups; ++i)
  1004.                                                 {
  1005.                                                         SMMRMGroupHeader& pGroup = pSrcMergedMesh->m_groups[i];
  1006.                                                         pDstMergedMesh->AddGroup(pGroup.instGroupId, pGroup.numSamples);
  1007.                                                 }
  1008.                                         }
  1009.                                 }
  1010.  
  1011.                                 pNodeClone = pDstMergedMesh;
  1012.  
  1013.                                 Get3DEngine()->RegisterEntity(pDstMergedMesh);
  1014.                         }
  1015.                 }
  1016.  
  1017.                 if (pNodeClone)
  1018.                 {
  1019.                         pNodeClone->SetRndFlags(ERF_CLONE_SOURCE, false);
  1020.                         pNodeClone->SetLayerId(pNode->GetLayerId());
  1021.                 }
  1022.         }
  1023. }
  1024.  
  1025. void CTerrain::ClearCloneSources()
  1026. {
  1027.         I3DEngine* p3DEngine = Get3DEngine();
  1028.  
  1029.         int numObjects = p3DEngine->GetObjectsByFlags(ERF_CLONE_SOURCE, NULL);
  1030.  
  1031.         if (numObjects == 0)
  1032.                 return;
  1033.  
  1034.         PodArray<IRenderNode*> objects;
  1035.         objects.resize(numObjects);
  1036.         p3DEngine->GetObjectsByFlags(ERF_CLONE_SOURCE, &objects[0]);
  1037.  
  1038.         for (int i = 0; i < numObjects; i++)
  1039.         {
  1040.                 IRenderNode* pNode = objects[i];
  1041.  
  1042.                 Get3DEngine()->DeleteRenderNode(pNode);
  1043.         }
  1044. }
  1045.  
downloadterran_edit.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