BVB Source Codes

CRYENGINE Show terrain_hmap.cpp Source code

Return Download CRYENGINE: download terrain_hmap.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_hmap.cpp
  5. //  Version:     v1.00
  6. //  Created:     28/5/2001 by Vladimir Kajalin
  7. //  Compilers:   Visual Studio.NET
  8. //  Description: highmap
  9. // -------------------------------------------------------------------------
  10. //  History:
  11. //
  12. ////////////////////////////////////////////////////////////////////////////
  13.  
  14. #include "StdAfx.h"
  15.  
  16. #include "terrain.h"
  17.  
  18. namespace
  19. {
  20. static inline uint32 encodeby1(uint32 n)
  21. {
  22.         n &= 0x0000ffff;
  23.         n = (n | (n << 8)) & 0x00FF00FF;
  24.         n = (n | (n << 4)) & 0x0F0F0F0F;
  25.         n = (n | (n << 2)) & 0x33333333;
  26.         n = (n | (n << 1)) & 0x55555555;
  27.         return n;
  28. }
  29. }
  30.  
  31. /* //TODO: NOT CURRENTLY SUPPORTED DUE TO NEW INTEGER DATA IMPLEMENTATION
  32.    static ILINE void SetHeightLocal( SRangeInfo & ri, int nX, int nY, float fHeight )
  33.    {
  34.    float fCompHeight = (ri.fRange>(0.01f/65535.f)) ? ((fHeight - ri.fOffset)/ri.fRange) : 0;
  35.    uint16 usNewZValue = ((uint16)CLAMP((int)fCompHeight, 0, 65535)) & ~STYPE_BIT_MASK;
  36.    uint16 usOldSurfTypes = ri.GetRawDataLocal(nX, nY) & STYPE_BIT_MASK;
  37.    ri.SetDataLocal(nX, nY, usNewZValue | usOldSurfTypes);
  38.    }
  39.  */
  40. static ILINE float GetHeightLocal(SRangeInfo const& ri, int nX, int nY, float fX, float fY)
  41. {
  42.         float fZ = ri.GetHeight(nX, nY) * (1.f - fX) * (1.f - fY)
  43.                    + ri.GetHeight(nX + 1, nY) * fX * (1.f - fY)
  44.                    + ri.GetHeight(nX, nY + 1) * (1.f - fX) * fY
  45.                    + ri.GetHeight(nX + 1, nY + 1) * fX * fY;
  46.  
  47.         return fZ;
  48. }
  49.  
  50. /*  //TODO: NOT CURRENTLY SUPPORTED DUE TO NEW INTEGER DATA IMPLEMENTATION
  51.    static ILINE void SetHeightUnits( SRangeInfo & ri, int nX_units, int nY_units, float fHeight )
  52.    {
  53.    ri.nModified = true;
  54.  
  55.    int nMask = ri.nSize-2;
  56.    if (ri.nUnitBitShift == 0)
  57.    {
  58.     // full lod is available
  59.     SetHeightLocal(ri, nX_units&nMask, nY_units&nMask, fHeight);
  60.    }
  61.    }
  62.  */
  63. static float GetHeightUnits(SRangeInfo const& ri, int nX_units, int nY_units, int nUnitToSectorBS)
  64. {
  65.         int nMask = ri.nSize - 2;
  66.  
  67.         if (ri.nUnitBitShift == 0)
  68.         {
  69.                 // full lod is available
  70.                 return ri.GetHeight(nX_units & nMask, nY_units & nMask);
  71.         }
  72.         else
  73.         {
  74.                 float fInvStep = (ri.nSize > 1) ? (1.f / ((1 << nUnitToSectorBS) / (ri.nSize - 1))) : 1.f;
  75.  
  76.                 // interpolate
  77.                 int nX = nX_units >> ri.nUnitBitShift;
  78.                 float fX = (nX_units * fInvStep) - nX;
  79.                 assert(fX + fInvStep <= 1.f);
  80.  
  81.                 int nY = nY_units >> ri.nUnitBitShift;
  82.                 float fY = (nY_units * fInvStep) - nY;
  83.                 assert(fY + fInvStep <= 1.f);
  84.  
  85.                 return GetHeightLocal(ri, nX & nMask, nY & nMask, fX, fY);
  86.         }
  87. }
  88.  
  89. static void Get4HeightsUnits(SRangeInfo const& ri, int nX_units, int nY_units, float afZ[4], int nUnitToSectorBS, int nSectorSizeUnits)
  90. {
  91.         int nMask = ri.nSize - 2;
  92.         if (ri.nUnitBitShift == 0)
  93.         {
  94.                 // full lod is available
  95.                 nX_units &= nMask;
  96.                 nY_units &= nMask;
  97.                 afZ[0] = ri.GetHeight(nX_units, nY_units);
  98.                 afZ[1] = ri.GetHeight(nX_units + 1, nY_units);
  99.                 afZ[2] = ri.GetHeight(nX_units, nY_units + 1);
  100.                 afZ[3] = ri.GetHeight(nX_units + 1, nY_units + 1);
  101.         }
  102.         else
  103.         {
  104.                 float fInvStep = (ri.nSize > 1) ? (1.f / (nSectorSizeUnits / (ri.nSize - 1))) : 1.f;
  105.  
  106.                 // interpolate
  107.                 int nX = nX_units >> ri.nUnitBitShift;
  108.                 float fX = (nX_units * fInvStep) - nX;
  109.                 assert(fX + fInvStep <= 1.f);
  110.  
  111.                 int nY = nY_units >> ri.nUnitBitShift;
  112.                 float fY = (nY_units * fInvStep) - nY;
  113.                 assert(fY + fInvStep <= 1.f);
  114.  
  115.                 nX &= nMask;
  116.                 nY &= nMask;
  117.                 afZ[0] = GetHeightLocal(ri, nX, nY, fX, fY);
  118.                 afZ[1] = GetHeightLocal(ri, nX, nY, fX + fInvStep, fY);
  119.                 afZ[2] = GetHeightLocal(ri, nX, nY, fX, fY + fInvStep);
  120.                 afZ[3] = GetHeightLocal(ri, nX, nY, fX + fInvStep, fY + fInvStep);
  121.         }
  122. }
  123.  
  124. float CHeightMap::GetZApr(float xWS, float yWS, int nSID) const
  125. {
  126. #ifdef SEG_WORLD
  127.         Vec3 v(xWS, yWS, 0);
  128.         nSID = Cry3DEngineBase::GetTerrain()->WorldToSegment(v, nSID);
  129.         xWS = v.x;
  130.         yWS = v.y;
  131. #endif
  132.  
  133.         if (!Cry3DEngineBase::GetTerrain()->GetParentNode(nSID))
  134.                 return TERRAIN_BOTTOM_LEVEL;
  135.  
  136.         float fZ;
  137.  
  138.         // convert into hmap space
  139.         float x1 = xWS * CTerrain::GetInvUnitSize();
  140.         float y1 = yWS * CTerrain::GetInvUnitSize();
  141.  
  142. #ifndef SEG_WORLD
  143.         if (!Cry3DEngineBase::GetTerrain() || x1 < 1 || y1 < 1)
  144.                 return TERRAIN_BOTTOM_LEVEL;
  145. #endif
  146.  
  147.         int nX = fastftol_positive(x1);
  148.         int nY = fastftol_positive(y1);
  149.  
  150.         int nHMSize = CTerrain::GetTerrainSize() / CTerrain::GetHeightMapUnitSize();
  151.  
  152. #ifndef SEG_WORLD
  153.         if (!Cry3DEngineBase::GetTerrain() || nX < 1 || nY < 1 || nX >= nHMSize || nY >= nHMSize)
  154.                 fZ = TERRAIN_BOTTOM_LEVEL;
  155.         else
  156. #endif
  157.         {
  158.                 float dx1 = x1 - nX;
  159.                 float dy1 = y1 - nY;
  160.  
  161.                 float afZCorners[4];
  162.  
  163.                 const CTerrainNode* pNode = Cry3DEngineBase::GetTerrain()->GetSecInfoUnits(nX, nY, nSID);
  164.  
  165.                 if (pNode && pNode->m_rangeInfo.pHMData)
  166.                 {
  167.                         Get4HeightsUnits(pNode->m_rangeInfo, nX, nY, afZCorners, GetTerrain()->m_nUnitsToSectorBitShift, pNode->GetSectorSizeInHeightmapUnits());
  168.  
  169.                         if (dx1 + dy1 < 1.f)
  170.                         {
  171.                                 // Lower triangle.
  172.                                 fZ = afZCorners[0] * (1.f - dx1 - dy1)
  173.                                      + afZCorners[1] * dx1
  174.                                      + afZCorners[2] * dy1;
  175.                         }
  176.                         else
  177.                         {
  178.                                 // Upper triangle.
  179.                                 fZ = afZCorners[3] * (dx1 + dy1 - 1.f)
  180.                                      + afZCorners[2] * (1.f - dx1)
  181.                                      + afZCorners[1] * (1.f - dy1);
  182.                         }
  183.                         if (fZ < TERRAIN_BOTTOM_LEVEL)
  184.                                 fZ = TERRAIN_BOTTOM_LEVEL;
  185.                 }
  186.                 else
  187.                         fZ = TERRAIN_BOTTOM_LEVEL;
  188.         }
  189.         return fZ;
  190. }
  191.  
  192. float CHeightMap::GetZMax(float x0, float y0, float x1, float y1, int nSID) const
  193. {
  194.         // Convert to grid units.
  195.         int nGridSize = CTerrain::GetTerrainSize() / CTerrain::GetHeightMapUnitSize();
  196.         int nX0 = clamp_tpl(int(x0 * CTerrain::GetInvUnitSize()), 0, nGridSize - 1);
  197.         int nY0 = clamp_tpl(int(y0 * CTerrain::GetInvUnitSize()), 0, nGridSize - 1);
  198.         int nX1 = clamp_tpl(int_ceil(x1 * CTerrain::GetInvUnitSize()), 0, nGridSize - 1);
  199.         int nY1 = clamp_tpl(int_ceil(y1 * CTerrain::GetInvUnitSize()), 0, nGridSize - 1);
  200.  
  201.         return GetZMaxFromUnits(nX0, nY0, nX1, nY1, nSID);
  202. }
  203.  
  204. bool CHeightMap::RayTrace(Vec3 const& vStart, Vec3 const& vEnd, SRayTrace* prt, int nSID)
  205. {
  206.         FUNCTION_PROFILER_3DENGINE;
  207.  
  208.         CTerrain* pTerrain = GetTerrain();
  209.  
  210.         if (!pTerrain->GetParentNode(nSID))
  211.                 return false;
  212.  
  213.         // Temp storage to avoid tests.
  214.         SRayTrace s_rt;
  215.         SRayTrace& rt = prt ? *prt : s_rt;
  216.  
  217.         float fUnitSize = (float)CTerrain::GetHeightMapUnitSize();
  218.         float fInvUnitSize = CTerrain::GetInvUnitSize();
  219.         int nGridSize = (int)(CTerrain::GetTerrainSize() * fInvUnitSize);
  220.  
  221.         // Convert to grid units.
  222.         Vec3 vDelta = vEnd - vStart;
  223.         float fMinZ = min(vStart.z, vEnd.z);
  224.  
  225.         int nX = clamp_tpl(int(vStart.x * fInvUnitSize), 0, nGridSize - 1);
  226.         int nY = clamp_tpl(int(vStart.y * fInvUnitSize), 0, nGridSize - 1);
  227.  
  228.         int nEndX = clamp_tpl(int(vEnd.x * fInvUnitSize), 0, nGridSize - 1);
  229.         int nEndY = clamp_tpl(int(vEnd.y * fInvUnitSize), 0, nGridSize - 1);
  230.  
  231.         for (;; )
  232.         {
  233.                 // Get heightmap node for current point.
  234.                 CTerrainNode const* pNode = pTerrain->GetSecInfoUnits(nX, nY, nSID);
  235.  
  236.                 int nStepUnits = 1;
  237.  
  238.                 // When entering new node, check with bounding box.
  239.                 if (pNode && pNode->m_rangeInfo.pHMData && fMinZ <= pNode->m_boxHeigtmapLocal.max.z)
  240.                 {
  241.                         SRangeInfo const& ri = pNode->m_rangeInfo;
  242.  
  243.                         // Evaluate individual sectors.
  244.                         assert((1 << (m_nUnitsToSectorBitShift - ri.nUnitBitShift)) == ri.nSize - 1);
  245.  
  246.                         // Get cell for starting point.
  247.                         int nType = ri.GetDataUnits(nX, nY) & SRangeInfo::e_index_hole;
  248.                         if (nType != SRangeInfo::e_index_hole)
  249.                         {
  250.                                 // Get cell vertex values.
  251.                                 float afZ[4];
  252.                                 Get4HeightsUnits(ri, nX, nY, afZ, pTerrain->m_nUnitsToSectorBitShift, pNode->GetSectorSizeInHeightmapUnits());
  253.  
  254.                                 // Further zmin check.
  255.                                 if (fMinZ <= afZ[0] || fMinZ <= afZ[1] || fMinZ <= afZ[2] || fMinZ <= afZ[3])
  256.                                 {
  257.                                         if (prt)
  258.                                         {
  259.                                                 IMaterial* pMat = pTerrain->GetSurfaceTypes(nSID)[nType].pLayerMat;
  260.                                                 ;
  261.                                                 prt->pMaterial = pMat;
  262.                                                 if (pMat && pMat->GetSubMtlCount() > 2)
  263.                                                         prt->pMaterial = pMat->GetSubMtl(2);
  264.                                         }
  265.  
  266.                                         // Select common point on both tris.
  267.                                         float fX0 = nX * fUnitSize;
  268.                                         float fY0 = nY * fUnitSize;
  269.                                         Vec3 vEndRel = vEnd - Vec3(fX0 + fUnitSize, fY0, afZ[1]);
  270.  
  271.                                         //
  272.                                         // Intersect with bottom triangle.
  273.                                         //
  274.                                         Vec3 vTriDir1(afZ[0] - afZ[1], afZ[0] - afZ[2], fUnitSize);
  275.                                         float fET1 = vEndRel * vTriDir1;
  276.                                         if (fET1 < 0.f)
  277.                                         {
  278.                                                 // End point below plane. Find intersection time.
  279.                                                 float fDT = vDelta * vTriDir1;
  280.                                                 if (fDT <= fET1)
  281.                                                 {
  282.                                                         rt.fInterp = 1.f - fET1 / fDT;
  283.                                                         rt.vHit = vStart + vDelta * rt.fInterp;
  284.  
  285.                                                         // Check against tri boundaries.
  286.                                                         if (rt.vHit.x >= fX0 && rt.vHit.y >= fY0 && rt.vHit.x + rt.vHit.y <= fX0 + fY0 + fUnitSize)
  287.                                                         {
  288.                                                                 rt.vNorm = vTriDir1.GetNormalized();
  289.                                                                 return true;
  290.                                                         }
  291.                                                 }
  292.                                         }
  293.  
  294.                                         //
  295.                                         // Intersect with top triangle.
  296.                                         //
  297.                                         Vec3 vTriDir2(afZ[2] - afZ[3], afZ[1] - afZ[3], fUnitSize);
  298.                                         float fET2 = vEndRel * vTriDir2;
  299.                                         if (fET2 < 0.f)
  300.                                         {
  301.                                                 // End point below plane. Find intersection time.
  302.                                                 float fDT = vDelta * vTriDir2;
  303.                                                 if (fDT <= fET2)
  304.                                                 {
  305.                                                         rt.fInterp = 1.f - fET2 / fDT;
  306.                                                         rt.vHit = vStart + vDelta * rt.fInterp;
  307.  
  308.                                                         // Check against tri boundaries.
  309.                                                         if (rt.vHit.x <= fX0 + fUnitSize && rt.vHit.y <= fY0 + fUnitSize && rt.vHit.x + rt.vHit.y >= fX0 + fY0 + fUnitSize)
  310.                                                         {
  311.                                                                 rt.vNorm = vTriDir2.GetNormalized();
  312.                                                                 return true;
  313.                                                         }
  314.                                                 }
  315.                                         }
  316.  
  317.                                         // Check for end point below terrain, to correct for leaks.
  318.                                         if (nX == nEndX && nY == nEndY)
  319.                                         {
  320.                                                 if (fET1 < 0.f)
  321.                                                 {
  322.                                                         // Lower tri.
  323.                                                         if (vEnd.x + vEnd.y <= fX0 + fY0 + fUnitSize)
  324.                                                         {
  325.                                                                 rt.fInterp = 1.f;
  326.                                                                 rt.vNorm = vTriDir1.GetNormalized();
  327.                                                                 rt.vHit = vEnd;
  328.                                                                 rt.vHit.z = afZ[0] - ((vEnd.x - fX0) * rt.vNorm.x + (vEnd.y - fY0) * rt.vNorm.y) / rt.vNorm.z;
  329.                                                                 return true;
  330.                                                         }
  331.                                                 }
  332.                                                 if (fET2 < 0.f)
  333.                                                 {
  334.                                                         // Upper tri.
  335.                                                         if (vEnd.x + vEnd.y >= fX0 + fY0 + fUnitSize)
  336.                                                         {
  337.                                                                 rt.fInterp = 1.f;
  338.                                                                 rt.vNorm = vTriDir2.GetNormalized();
  339.                                                                 rt.vHit = vEnd;
  340.                                                                 rt.vHit.z = afZ[3] - ((vEnd.x - fX0 - fUnitSize) * rt.vNorm.x + (vEnd.y - fY0 - fUnitSize) * rt.vNorm.y) / rt.vNorm.z;
  341.                                                                 return true;
  342.                                                         }
  343.                                                 }
  344.                                         }
  345.                                 }
  346.                         }
  347.                 }
  348.                 else
  349.                 {
  350.                         // Skip entire node.
  351.                         nStepUnits = 1 << (m_nUnitsToSectorBitShift + 0 /*pNode->m_nTreeLevel*/);
  352.                         assert(!pNode || nStepUnits == int(pNode->m_boxHeigtmapLocal.max.x - pNode->m_boxHeigtmapLocal.min.x) * fInvUnitSize);
  353.                         assert(!pNode || pNode->m_nTreeLevel == 0);
  354.                 }
  355.  
  356.                 // Step out of cell.
  357.                 int nX1 = nX & ~(nStepUnits - 1);
  358.                 if (vDelta.x >= 0.f)
  359.                         nX1 += nStepUnits;
  360.                 float fX = (float)(nX1 * CTerrain::GetHeightMapUnitSize());
  361.  
  362.                 int nY1 = nY & ~(nStepUnits - 1);
  363.                 if (vDelta.y >= 0.f)
  364.                         nY1 += nStepUnits;
  365.                 float fY = (float)(nY1 * CTerrain::GetHeightMapUnitSize());
  366.  
  367.                 if (abs((fX - vStart.x) * vDelta.y) < abs((fY - vStart.y) * vDelta.x))
  368.                 {
  369.                         if (fX * vDelta.x >= vEnd.x * vDelta.x)
  370.                                 break;
  371.                         if (nX1 > nX)
  372.                         {
  373.                                 nX = nX1;
  374.                                 if (nX >= nGridSize)
  375.                                         break;
  376.                         }
  377.                         else
  378.                         {
  379.                                 nX = nX1 - 1;
  380.                                 if (nX < 0)
  381.                                         break;
  382.                         }
  383.                 }
  384.                 else
  385.                 {
  386.                         if (fY * vDelta.y >= vEnd.y * vDelta.y)
  387.                                 break;
  388.                         if (nY1 > nY)
  389.                         {
  390.                                 nY = nY1;
  391.                                 if (nY >= nGridSize)
  392.                                         break;
  393.                         }
  394.                         else
  395.                         {
  396.                                 nY = nY1 - 1;
  397.                                 if (nY < 0)
  398.                                         break;
  399.                         }
  400.                 }
  401.         }
  402.  
  403.         return false;
  404. }
  405.  
  406. bool CHeightMap::IntersectWithHeightMap(Vec3 vStartPoint, Vec3 vStopPoint, float fDist, int nMaxTestsToScip, int nSID)
  407. {
  408.         // FUNCTION_PROFILER_3DENGINE;
  409.         // convert into hmap space
  410.         float fInvUnitSize = CTerrain::GetInvUnitSize();
  411.         vStopPoint.x *= fInvUnitSize;
  412.         vStopPoint.y *= fInvUnitSize;
  413.         vStartPoint.x *= fInvUnitSize;
  414.         vStartPoint.y *= fInvUnitSize;
  415.         fDist *= fInvUnitSize;
  416.  
  417.         int nHMSize = CTerrain::GetTerrainSize() / CTerrain::GetHeightMapUnitSize();
  418.  
  419.         // clamp points
  420.         const bool cClampStart = (vStartPoint.x < 0) | (vStartPoint.y < 0) | (vStartPoint.x > nHMSize) | (vStartPoint.y > nHMSize);
  421.         if (cClampStart)
  422.         {
  423.                 const float fHMSize = (float)nHMSize;
  424.                 AABB boxHM(Vec3(0.f, 0.f, 0.f), Vec3(fHMSize, fHMSize, fHMSize));
  425.  
  426.                 Lineseg ls;
  427.                 ls.start = vStartPoint;
  428.                 ls.end = vStopPoint;
  429.  
  430.                 Vec3 vRes;
  431.                 if (Intersect::Lineseg_AABB(ls, boxHM, vRes) == 0x01)
  432.                         vStartPoint = vRes;
  433.                 else
  434.                         return false;
  435.         }
  436.  
  437.         const bool cClampStop = (vStopPoint.x < 0) | (vStopPoint.y < 0) | (vStopPoint.x > nHMSize) | (vStopPoint.y > nHMSize);
  438.         if (cClampStop)
  439.         {
  440.                 const float fHMSize = (float)nHMSize;
  441.                 AABB boxHM(Vec3(0.f, 0.f, 0.f), Vec3(fHMSize, fHMSize, fHMSize));
  442.  
  443.                 Lineseg ls;
  444.                 ls.start = vStopPoint;
  445.                 ls.end = vStartPoint;
  446.  
  447.                 Vec3 vRes;
  448.                 if (Intersect::Lineseg_AABB(ls, boxHM, vRes) == 0x01)
  449.                         vStopPoint = vRes;
  450.                 else
  451.                         return false;
  452.         }
  453.  
  454.         Vec3 vDir = (vStopPoint - vStartPoint);
  455.  
  456.         int nSteps = fastftol_positive(fDist / GetCVars()->e_TerrainOcclusionCullingStepSize); // every 4 units
  457.         if (nSteps != 0)
  458.         {
  459.                 switch (GetCVars()->e_TerrainOcclusionCulling)
  460.                 {
  461.                 case 4:                     // far objects are culled less precise but with far hills as well (same culling speed)
  462.                         if (nSteps > GetCVars()->e_TerrainOcclusionCullingMaxSteps)
  463.                                 nSteps = GetCVars()->e_TerrainOcclusionCullingMaxSteps;
  464.                         vDir /= (float)nSteps;
  465.                         break;
  466.                 default:                      // far hills are not culling
  467.                         vDir /= (float)nSteps;
  468.                         if (nSteps > GetCVars()->e_TerrainOcclusionCullingMaxSteps)
  469.                                 nSteps = GetCVars()->e_TerrainOcclusionCullingMaxSteps;
  470.                         break;
  471.                 }
  472.         }
  473.  
  474.         // scan hmap in sector
  475.  
  476.         Vec3 vPos = vStartPoint;
  477.  
  478.         int nTest = 0;
  479.  
  480.         CTerrain* const __restrict pTerrain = Cry3DEngineBase::GetTerrain();
  481.         const int nUnitsToSectorBitShift = m_nUnitsToSectorBitShift;
  482.         for (nTest = 0; nTest < nSteps && nTest < nMaxTestsToScip; nTest++)
  483.         {
  484.                 // leave the underground first
  485.                 if (IsPointUnderGround(pTerrain, nUnitsToSectorBitShift, fastround_positive(vPos.x), fastround_positive(vPos.y), vPos.z, nSID))
  486.                         vPos += vDir;
  487.                 else
  488.                         break;
  489.         }
  490.  
  491.         nMaxTestsToScip = min(nMaxTestsToScip, 4);
  492.  
  493.         for (; nTest < nSteps - nMaxTestsToScip; nTest++)
  494.         {
  495.                 vPos += vDir;
  496.                 if (IsPointUnderGround(pTerrain, nUnitsToSectorBitShift, fastround_positive(vPos.x), fastround_positive(vPos.y), vPos.z, nSID))
  497.                         return true;
  498.         }
  499.  
  500.         return false;
  501. }
  502.  
  503. bool CHeightMap::GetHole(const int x, const int y, int nSID)  const
  504. {
  505.         int nX_units = x >> m_nBitShift;
  506.         int nY_units = y >> m_nBitShift;
  507.         int nTerrainSize_units = (CTerrain::GetTerrainSize() >> m_nBitShift);
  508.  
  509.         if (nX_units < 0 || nX_units >= nTerrainSize_units || nY_units < 0 || nY_units >= nTerrainSize_units)
  510.                 return true;
  511.  
  512.         return GetSurfTypefromUnits(nX_units, nY_units, nSID) == SRangeInfo::e_hole;
  513. }
  514.  
  515. float CHeightMap::GetZSafe(int x, int y, int nSID)
  516. {
  517.         if (x >= 0 && y >= 0 && x < CTerrain::GetTerrainSize() && y < CTerrain::GetTerrainSize())
  518.                 return max(GetZ(x, y, nSID), (float)TERRAIN_BOTTOM_LEVEL);
  519.  
  520.         return TERRAIN_BOTTOM_LEVEL;
  521. }
  522.  
  523. uint8 CHeightMap::GetSurfaceTypeID(int x, int y, int nSID) const
  524. {
  525.         if (x >= 0 && y >= 0 && x <= CTerrain::GetTerrainSize() && y <= CTerrain::GetTerrainSize())
  526.                 return GetSurfTypefromUnits(x >> m_nBitShift, y >> m_nBitShift, nSID);
  527.  
  528.         return SRangeInfo::e_undefined;
  529. }
  530.  
  531. float CHeightMap::GetZ(int x, int y, int nSID, bool bUpdatePos) const
  532. {
  533. #ifdef SEG_WORLD
  534.         if (nSID < 0 || bUpdatePos)
  535.         {
  536.                 Vec3 v((float)x, (float)y, 0);
  537.                 nSID = Cry3DEngineBase::GetTerrain()->WorldToSegment(v, nSID);
  538.                 x = (int)v.x;
  539.                 y = (int)v.y;
  540.         }
  541. #endif
  542.  
  543.         if (!Cry3DEngineBase::GetTerrain()->GetParentNode(nSID))
  544.                 return TERRAIN_BOTTOM_LEVEL;
  545.  
  546.         return GetZfromUnits(x >> m_nBitShift, y >> m_nBitShift, nSID);
  547. }
  548.  
  549. void CHeightMap::SetZ(const int x, const int y, float fHeight, int nSID)
  550. {
  551.         return SetZfromUnits(x >> m_nBitShift, y >> m_nBitShift, fHeight, nSID);
  552. }
  553.  
  554. uint8 CHeightMap::GetSurfTypefromUnits(uint32 nX_units, uint32 nY_units, int nSID) const
  555. {
  556.         if (CTerrain* pTerrain = Cry3DEngineBase::GetTerrain())
  557.         {
  558.                 pTerrain->ClampUnits(nX_units, nY_units);
  559.                 const CTerrainNode* pNode = pTerrain->GetSecInfoUnits(nX_units, nY_units, nSID);
  560.                 if (pNode)
  561.                 {
  562.                         const SRangeInfo& ri = pNode->m_rangeInfo;
  563.  
  564.                         if (ri.pHMData && ri.pSTPalette)
  565.                         {
  566.                                 int nType = ri.GetDataUnits(nX_units, nY_units) & SRangeInfo::e_index_hole;
  567.  
  568.                                 return ri.pSTPalette[nType];
  569.                         }
  570.                 }
  571.         }
  572.         return SRangeInfo::e_undefined;
  573. }
  574.  
  575. float CHeightMap::GetZfromUnits(uint32 nX_units, uint32 nY_units, int nSID) const
  576. {
  577.         if (CTerrain* pTerrain = Cry3DEngineBase::GetTerrain())
  578.         {
  579.                 pTerrain->ClampUnits(nX_units, nY_units);
  580.                 CTerrainNode* pNode = pTerrain->GetSecInfoUnits(nX_units, nY_units, nSID);
  581.                 if (pNode)
  582.                 {
  583.                         SRangeInfo& ri = pNode->m_rangeInfo;
  584.                         if (ri.pHMData)
  585.                         {
  586.                                 return GetHeightUnits(ri, nX_units, nY_units, pTerrain->m_nUnitsToSectorBitShift);
  587.                         }
  588.                 }
  589.         }
  590.         return 0;
  591. }
  592.  
  593. void CHeightMap::SetZfromUnits(uint32 nX_units, uint32 nY_units, float fHeight, int nSID)
  594. {
  595.         if (!Cry3DEngineBase::GetTerrain())
  596.                 return;
  597.  
  598.         assert(0); //TODO: NOT CURRENTLY SUPPORTED DUE TO NEW INTEGER DATA IMPLEMENTATION
  599.         /*
  600.            Cry3DEngineBase::GetTerrain()->ClampUnits(nX_units, nY_units);
  601.            CTerrainNode * pNode = Cry3DEngineBase::GetTerrain()->GetSecInfoUnits(nX_units, nY_units, nSID);
  602.            if(!pNode)
  603.             return;
  604.            SRangeInfo& ri = pNode->m_rangeInfo;
  605.            if (!ri.pHMData)
  606.             return;
  607.  
  608.            SetHeightUnits( ri, nX_units, nY_units, fHeight );*/
  609. }
  610.  
  611. float CHeightMap::GetZMaxFromUnits(uint32 nX0_units, uint32 nY0_units, uint32 nX1_units, uint32 nY1_units, int nSID) const
  612. {
  613.         if (!Cry3DEngineBase::GetTerrain())
  614.                 return TERRAIN_BOTTOM_LEVEL;
  615.  
  616.         Array2d<struct CTerrainNode*>& sectorLayer = Cry3DEngineBase::GetTerrain()->m_arrSecInfoPyramid[nSID][0];
  617.         uint32 nLocalMask = (1 << m_nUnitsToSectorBitShift) - 1;
  618.  
  619.         uint32 nSizeXY = Cry3DEngineBase::GetTerrain()->GetTerrainSize() >> m_nBitShift;
  620.         assert(nX0_units <= nSizeXY && nY0_units <= nSizeXY);
  621.         assert(nX1_units <= nSizeXY && nY1_units <= nSizeXY);
  622.  
  623.         float fZMax = TERRAIN_BOTTOM_LEVEL;
  624.  
  625.         // Iterate sectors.
  626.         uint32 nX0_sector = nX0_units >> m_nUnitsToSectorBitShift,
  627.                nX1_sector = nX1_units >> m_nUnitsToSectorBitShift,
  628.                nY0_sector = nY0_units >> m_nUnitsToSectorBitShift,
  629.                nY1_sector = nY1_units >> m_nUnitsToSectorBitShift;
  630.         for (uint32 nX_sector = nX0_sector; nX_sector <= nX1_sector; nX_sector++)
  631.         {
  632.                 for (uint32 nY_sector = nY0_sector; nY_sector <= nY1_sector; nY_sector++)
  633.                 {
  634.                         CTerrainNode& node = *sectorLayer[nX_sector][nY_sector];
  635.                         SRangeInfo& ri = node.m_rangeInfo;
  636.                         if (!ri.pHMData)
  637.                                 continue;
  638.  
  639.                         assert((1 << (m_nUnitsToSectorBitShift - ri.nUnitBitShift)) == ri.nSize - 1);
  640.  
  641.                         // Iterate points in sector.
  642.                         uint32 nX0_pt = (nX_sector == nX0_sector ? nX0_units & nLocalMask : 0) >> ri.nUnitBitShift;
  643.                         uint32 nX1_pt = (nX_sector == nX1_sector ? nX1_units & nLocalMask : nLocalMask) >> ri.nUnitBitShift;
  644.                         ;
  645.                         uint32 nY0_pt = (nY_sector == nY0_sector ? nY0_units & nLocalMask : 0) >> ri.nUnitBitShift;
  646.                         ;
  647.                         uint32 nY1_pt = (nY_sector == nY1_sector ? nY1_units & nLocalMask : nLocalMask) >> ri.nUnitBitShift;
  648.                         ;
  649.  
  650.                         float fSectorZMax;
  651.                         if ((nX1_pt - nX0_pt + 1) * (nY1_pt - nY0_pt + 1) >= (uint32)(ri.nSize - 1) * (ri.nSize - 1))
  652.                         {
  653.                                 fSectorZMax = node.m_boxHeigtmapLocal.max.z;
  654.                         }
  655.                         else
  656.                         {
  657.                                 uint32 nSectorZMax = 0;
  658.                                 for (uint32 nX_pt = nX0_pt; nX_pt <= nX1_pt; nX_pt++)
  659.                                 {
  660.                                         for (uint32 nY_pt = nY0_pt; nY_pt <= nY1_pt; nY_pt++)
  661.                                         {
  662.                                                 int nCellLocal = nX_pt * ri.nSize + nY_pt;
  663.                                                 assert(nCellLocal >= 0 && nCellLocal < ri.nSize * ri.nSize);
  664.                                                 uint32 rawdata = ri.GetRawDataByIndex(nCellLocal);
  665.                                                 nSectorZMax = max(nSectorZMax, rawdata);
  666.                                         }
  667.                                 }
  668.                                 fSectorZMax = ri.fOffset + (nSectorZMax & ~SRangeInfo::e_index_hole) * ri.fRange;
  669.                         }
  670.  
  671.                         fZMax = max(fZMax, fSectorZMax);
  672.                 }
  673.         }
  674.         return fZMax;
  675. }
  676.  
  677. bool CHeightMap::IsMeshQuadFlipped(const int x, const int y, const int nUnitSize, int nSID) const
  678. {
  679.         bool bFlipped = false;
  680.  
  681.         // Flip winding order to prevent surface type interpolation over long edges
  682.         int nType10 = GetSurfaceTypeID(x + nUnitSize, y, nSID);
  683.         int nType01 = GetSurfaceTypeID(x, y + nUnitSize, nSID);
  684.  
  685.         if (nType10 != nType01)
  686.         {
  687.                 int nType00 = GetSurfaceTypeID(x, y, nSID);
  688.                 int nType11 = GetSurfaceTypeID(x + nUnitSize, y + nUnitSize, nSID);
  689.  
  690.                 if ((nType10 == nType00 && nType10 == nType11)
  691.                     || (nType01 == nType00 && nType01 == nType11))
  692.                 {
  693.                         bFlipped = true;
  694.                 }
  695.         }
  696.  
  697.         return bFlipped;
  698. }
  699.  
  700. bool CHeightMap::IsPointUnderGround(CTerrain* const __restrict pTerrain,
  701.                                     int nUnitsToSectorBitShift,
  702.                                     uint32 nX_units,
  703.                                     uint32 nY_units,
  704.                                     float fTestZ,
  705.                                     int nSID)
  706. {
  707.         //  FUNCTION_PROFILER_3DENGINE;
  708.  
  709.         if (GetCVars()->e_TerrainOcclusionCullingDebug)
  710.         {
  711.                 Vec3 vTerPos(0, 0, 0);
  712.                 vTerPos.Set((float)(nX_units * CTerrain::GetHeightMapUnitSize()), (float)(nY_units * CTerrain::GetHeightMapUnitSize()), 0);
  713.                 vTerPos.z = pTerrain->GetZfromUnits(nX_units, nY_units, nSID);
  714.                 DrawSphere(vTerPos, 1.f, Col_Red);
  715.         }
  716.  
  717.         pTerrain->ClampUnits(nX_units, nY_units);
  718.         CTerrainNode* pNode = pTerrain->GetSecInfoUnits(nX_units, nY_units, nSID);
  719.         if (!pNode)
  720.                 return false;
  721.  
  722.         SRangeInfo& ri = pNode->m_rangeInfo;
  723.  
  724.         if (!ri.pHMData || (pNode->m_bNoOcclusion != 0) || (pNode->m_bHasHoles != 0))
  725.                 return false;
  726.  
  727.         if (fTestZ < ri.fOffset)
  728.                 return true;
  729.  
  730.         float fZ = GetHeightUnits(ri, nX_units, nY_units, GetTerrain()->m_nUnitsToSectorBitShift);
  731.  
  732.         return fTestZ < fZ;
  733. }
  734.  
  735. CHeightMap::SCachedHeight CHeightMap::m_arrCacheHeight[nHMCacheSize * nHMCacheSize];
  736. CHeightMap::SCachedSurfType CHeightMap::m_arrCacheSurfType[nHMCacheSize * nHMCacheSize];
  737.  
  738. float CHeightMap::GetHeightFromUnits_Callback(int ix, int iy)
  739. {
  740.         const uint32 idx = encodeby1(ix & ((nHMCacheSize - 1))) | (encodeby1(iy & ((nHMCacheSize - 1))) << 1);
  741.         CHeightMap::SCachedHeight& rCache = m_arrCacheHeight[idx];
  742.         if (rCache.x == ix && rCache.y == iy)
  743.                 return rCache.fHeight;
  744.  
  745.         assert(sizeof(m_arrCacheHeight[0]) == 8);
  746.  
  747.         rCache.x = ix;
  748.         rCache.y = iy;
  749.         rCache.fHeight = Cry3DEngineBase::GetTerrain()->GetZfromUnits(ix, iy, GetDefSID());
  750.  
  751.         return rCache.fHeight;
  752. }
  753.  
  754. unsigned char CHeightMap::GetSurfaceTypeFromUnits_Callback(int ix, int iy)
  755. {
  756.         /*
  757.            static int nAll=0;
  758.            static int nBad=0;
  759.  
  760.            if(nAll && nAll/1000000*1000000 == nAll)
  761.            {
  762.            Error("SurfaceType_RealReads = %.2f", (float)nBad/nAll);
  763.            nAll=0;
  764.            nBad=0;
  765.  
  766.            if(sizeof(m_arrCacheSurfType[0][0]) != 4)
  767.             Error("CHeightMap::GetSurfaceTypeFromUnits_Callback:  sizeof(m_arrCacheSurfType[0][0]) != 4");
  768.            }
  769.  
  770.            nAll++;
  771.          */
  772.  
  773.         const uint32 idx = encodeby1(ix & ((nHMCacheSize - 1))) | (encodeby1(iy & ((nHMCacheSize - 1))) << 1);
  774.         CHeightMap::SCachedSurfType& rCache = m_arrCacheSurfType[idx];
  775.         if (rCache.x == ix && rCache.y == iy)
  776.                 return rCache.surfType;
  777.  
  778.         //  nBad++;
  779.  
  780.         rCache.x = ix;
  781.         rCache.y = iy;
  782.         rCache.surfType = Cry3DEngineBase::GetTerrain()->GetSurfTypefromUnits(ix, iy, GetDefSID());
  783.  
  784.         return rCache.surfType;
  785. }
  786.  
downloadterrain_hmap.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