BVB Source Codes

CRYENGINE Show terrain_node_compile.cpp Source code

Return Download CRYENGINE: download terrain_node_compile.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  File name:   terrain_node.cpp
  5. //  Version:     v1.00
  6. //  Created:     28/5/2001 by Vladimir Kajalin
  7. //  Compilers:   Visual Studio.NET
  8. //  Description: terrain node
  9. // -------------------------------------------------------------------------
  10. //  History:
  11. //
  12. ////////////////////////////////////////////////////////////////////////////
  13.  
  14. #include "StdAfx.h"
  15. #include "terrain_sector.h"
  16. #include "terrain.h"
  17. #include "ObjMan.h"
  18. #include "VisAreas.h"
  19.  
  20. #define TERRAIN_NODE_CHUNK_VERSION 7
  21.  
  22. int CTerrainNode::Load(uint8*& f, int& nDataSize, EEndian eEndian, bool bSectorPalettes, SHotUpdateInfo* pExportInfo) { return Load_T(f, nDataSize, eEndian, bSectorPalettes, pExportInfo); }
  23. int CTerrainNode::Load(FILE*& f, int& nDataSize, EEndian eEndian, bool bSectorPalettes, SHotUpdateInfo* pExportInfo)  { return Load_T(f, nDataSize, eEndian, bSectorPalettes, pExportInfo); }
  24.  
  25. int CTerrainNode::FTell(uint8*& f)                                                                                    { return -1; }
  26. int CTerrainNode::FTell(FILE*& f)                                                                                     { return GetPak()->FTell(f); }
  27.  
  28. template<class T>
  29. int CTerrainNode::Load_T(T*& f, int& nDataSize, EEndian eEndian, bool bSectorPalettes, SHotUpdateInfo* pExportInfo)
  30. {
  31.         const AABB* pAreaBox = (pExportInfo && !pExportInfo->areaBox.IsReset()) ? &pExportInfo->areaBox : NULL;
  32.  
  33.         if (pAreaBox && !Overlap::AABB_AABB(GetBBox(), *pAreaBox))
  34.                 return 0;
  35.  
  36.         // set node data
  37.         STerrainNodeChunk chunk;
  38.         if (!CTerrain::LoadDataFromFile(&chunk, 1, f, nDataSize, eEndian))
  39.                 return 0;
  40.         assert(chunk.nChunkVersion >= 5 && chunk.nChunkVersion <= TERRAIN_NODE_CHUNK_VERSION);
  41.         if (chunk.nChunkVersion < 5 || chunk.nChunkVersion > TERRAIN_NODE_CHUNK_VERSION)
  42.                 return 0;
  43.  
  44.         // set error levels, bounding boxes and some flags
  45.         m_boxHeigtmapLocal = chunk.boxHeightmap;
  46.         m_boxHeigtmapLocal.max.z = max(m_boxHeigtmapLocal.max.z, GetTerrain()->GetWaterLevel());
  47.         m_bHasHoles = chunk.bHasHoles;
  48.         m_rangeInfo.fOffset = chunk.fOffset;
  49.         m_rangeInfo.fRange = chunk.fRange;
  50.         m_rangeInfo.nSize = chunk.nSize;
  51.         SAFE_DELETE_ARRAY(m_rangeInfo.pHMData);
  52.         m_rangeInfo.pSTPalette = NULL;
  53.         m_rangeInfo.UpdateBitShift(GetTerrain()->m_nUnitsToSectorBitShift);
  54.         m_rangeInfo.nModified = false;
  55.  
  56.         {
  57.                 float fMin = m_rangeInfo.fOffset;
  58.                 float fMax = m_rangeInfo.fOffset + 0xFFF0 * m_rangeInfo.fRange;
  59.  
  60.                 const unsigned mask12bit = (1 << 12) - 1;
  61.                 const int inv5cm = 20;
  62.  
  63.                 int iOffset = int(fMin * inv5cm);
  64.                 int iRange = int((fMax - fMin) * inv5cm);
  65.                 int iStep = iRange ? (iRange + mask12bit - 1) / mask12bit : 1;
  66.  
  67.                 iRange /= iStep;
  68.  
  69.                 m_rangeInfo.iOffset = iOffset;
  70.                 m_rangeInfo.iRange = iRange;
  71.                 m_rangeInfo.iStep = iStep;
  72.         }
  73.  
  74.         m_nNodeHMDataOffset = -1;
  75.         if (m_rangeInfo.nSize)
  76.         {
  77.                 m_rangeInfo.pHMData = new uint16[((m_rangeInfo.nSize * m_rangeInfo.nSize + 7) / 8) * 8];  // Align up to 16 bytes for console unaligned vector loads
  78.                 m_nNodeHMDataOffset = FTell(f);
  79.                 if (!CTerrain::LoadDataFromFile(m_rangeInfo.pHMData, m_rangeInfo.nSize * m_rangeInfo.nSize, f, nDataSize, eEndian))
  80.                         return 0;
  81.                 if (chunk.nChunkVersion != 5)
  82.                         CTerrain::LoadDataFromFile_FixAllignemt(f, nDataSize);
  83.  
  84.                 if (chunk.nChunkVersion < 7)
  85.                 {
  86.                         RescaleToInt();
  87.                 }
  88.         }
  89.  
  90.         // load LOD errors
  91.         delete[] m_pGeomErrors;
  92.         m_pGeomErrors = new float[GetTerrain()->m_nUnitsToSectorBitShift];
  93.         if (!CTerrain::LoadDataFromFile(m_pGeomErrors, GetTerrain()->m_nUnitsToSectorBitShift, f, nDataSize, eEndian))
  94.                 return 0;
  95.         assert(m_pGeomErrors[0] == 0);
  96.  
  97.         // load used surf types
  98.         for (int i = 0; i < m_lstSurfaceTypeInfo.Count(); i++)
  99.                 m_lstSurfaceTypeInfo[i].DeleteRenderMeshes(GetRenderer());
  100.         m_lstSurfaceTypeInfo.Clear();
  101.  
  102.         m_lstSurfaceTypeInfo.PreAllocate(chunk.nSurfaceTypesNum, chunk.nSurfaceTypesNum);
  103.  
  104.         if (chunk.nSurfaceTypesNum)
  105.         {
  106.                 uint8* pTypes = new uint8[chunk.nSurfaceTypesNum];  // TODO: avoid temporary allocations
  107.  
  108.                 if (!CTerrain::LoadDataFromFile(pTypes, chunk.nSurfaceTypesNum, f, nDataSize, eEndian))
  109.                         return 0;
  110.  
  111.                 for (int i = 0; i < m_lstSurfaceTypeInfo.Count() && i < SRangeInfo::e_hole; i++)
  112.                         m_lstSurfaceTypeInfo[i].pSurfaceType = &GetTerrain()->m_SSurfaceType[m_nSID][min((int)pTypes[i], (int)SRangeInfo::e_undefined)];
  113.  
  114.                 if (!m_pChilds)
  115.                 {
  116.                         // For leaves, we reconstruct the sector's surface type palette from the surface type array.
  117.                         m_rangeInfo.pSTPalette = new uchar[SRangeInfo::e_palette_size];
  118.                         for (int i = 0; i < SRangeInfo::e_index_hole; i++)
  119.                                 m_rangeInfo.pSTPalette[i] = SRangeInfo::e_undefined;
  120.  
  121.                         m_rangeInfo.pSTPalette[SRangeInfo::e_index_hole] = SRangeInfo::e_hole;
  122.  
  123.                         // Check which palette entries are actually used in the sector. We need to map all of them to global IDs.
  124.                         int nDataCount = m_rangeInfo.nSize * (m_rangeInfo.nSize - 1);
  125.                         int nUsedPaletteEntriesCount = 0;
  126.                         bool UsedPaletteEntries[SRangeInfo::e_palette_size];
  127.                         memset(UsedPaletteEntries, 0, sizeof(UsedPaletteEntries));
  128.                         if (m_rangeInfo.pHMData)
  129.                         {
  130.                                 for (int i = 0; i < nDataCount; i++)
  131.                                 {
  132.                                         if ((i + 1) % m_rangeInfo.nSize)
  133.                                                 UsedPaletteEntries[m_rangeInfo.GetSurfaceTypeByIndex(i)] = true;
  134.                                 }
  135.                         }
  136.  
  137.                         for (int i = 0; i < SRangeInfo::e_index_undefined; i++)
  138.                         {
  139.                                 if (UsedPaletteEntries[i])
  140.                                         nUsedPaletteEntriesCount++;
  141.                         }
  142.  
  143.                         // Get the first nUsedPaletteEntriesCount entries from m_lstSurfaceTypeInfo and put them into the used entries
  144.                         // of the palette, skipping the unused entries.
  145.                         int nCurrentListEntry = 0;
  146.                         assert(nUsedPaletteEntriesCount <= m_lstSurfaceTypeInfo.Count());
  147.                         if (m_rangeInfo.pHMData && bSectorPalettes)
  148.                         {
  149.                                 for (int i = 0; i < SRangeInfo::e_index_undefined; i++)
  150.                                 {
  151.                                         if (UsedPaletteEntries[i])
  152.                                         {
  153.                                                 m_rangeInfo.pSTPalette[i] = pTypes[nCurrentListEntry];
  154.                                                 //!!! shielding a problem
  155.                                                 if (nCurrentListEntry + 1 < chunk.nSurfaceTypesNum)
  156.                                                         ++nCurrentListEntry;
  157.                                         }
  158.                                 }
  159.                         }
  160.                         else
  161.                                 // In old levels, no palette had been saved, so create a trivial palette (trying to decode will yield garbage).
  162.                                 for (int i = 0; i < SRangeInfo::e_index_undefined; i++)
  163.                                 {
  164.                                         if (UsedPaletteEntries[i])
  165.                                                 m_rangeInfo.pSTPalette[i] = i;
  166.                                 }
  167.                 }
  168.  
  169.                 delete[] pTypes;
  170.  
  171.                 if (chunk.nChunkVersion != 5)
  172.                         CTerrain::LoadDataFromFile_FixAllignemt(f, nDataSize);
  173.         }
  174.  
  175.         // count number of nodes saved
  176.         int nNodesNum = 1;
  177.  
  178.         // process childs
  179.         for (int i = 0; m_pChilds && i < 4; i++)
  180.                 nNodesNum += m_pChilds[i].Load_T(f, nDataSize, eEndian, bSectorPalettes, pExportInfo);
  181.  
  182.         return nNodesNum;
  183. }
  184.  
  185. void CTerrainNode::RescaleToInt()
  186. {
  187.         if (m_rangeInfo.nSize && m_rangeInfo.pHMData)
  188.         {
  189.                 const float fRange = m_rangeInfo.fRange;
  190.                 const float fMin = m_rangeInfo.fOffset;
  191.  
  192.                 const int step = m_rangeInfo.iStep;
  193.                 const int inv5cm = 20;
  194.  
  195.                 uint16* hmap = m_rangeInfo.pHMData;
  196.  
  197.                 for (int i = 0, size = m_rangeInfo.nSize * m_rangeInfo.nSize; i < size; i++)
  198.                 {
  199.                         uint16 hraw = hmap[i];
  200.                         float height = fMin + (0xFFF0 & hraw) * fRange;
  201.                         uint16 hdec = int((height - fMin) * inv5cm) / step;
  202.  
  203.                         hmap[i] = (hraw & 0xF) | (hdec << 4);
  204.                 }
  205.         }
  206. }
  207.  
  208. void CTerrainNode::ReleaseHoleNodes()
  209. {
  210.         if (!m_pChilds)
  211.                 return;
  212.  
  213.         if (m_bHasHoles == 2)
  214.         {
  215.                 SAFE_DELETE_ARRAY(m_pChilds);
  216.         }
  217.         else
  218.         {
  219.                 for (int i = 0; i < 4; i++)
  220.                         m_pChilds[i].ReleaseHoleNodes();
  221.         }
  222. }
  223.  
  224. int CTerrainNode::ReloadModifiedHMData(FILE* f)
  225. {
  226.         if (m_rangeInfo.nSize && m_nNodeHMDataOffset >= 0 && m_rangeInfo.nModified)
  227.         {
  228.                 m_rangeInfo.nModified = false;
  229.  
  230.                 GetPak()->FSeek(f, m_nNodeHMDataOffset, SEEK_SET);
  231.                 int nDataSize = m_rangeInfo.nSize * m_rangeInfo.nSize * sizeof(m_rangeInfo.pHMData[0]);
  232.                 if (!CTerrain::LoadDataFromFile(m_rangeInfo.pHMData, m_rangeInfo.nSize * m_rangeInfo.nSize, f, nDataSize, m_pTerrain->m_eEndianOfTexture))
  233.                         return 0;
  234.         }
  235.  
  236.         // process childs
  237.         for (int i = 0; m_pChilds && i < 4; i++)
  238.                 m_pChilds[i].ReloadModifiedHMData(f);
  239.  
  240.         return 1;
  241. }
  242.  
  243. int CTerrainNode::GetData(byte*& pData, int& nDataSize, EEndian eEndian, SHotUpdateInfo* pExportInfo)
  244. {
  245.         const AABB* pAreaBox = (pExportInfo && !pExportInfo->areaBox.IsReset()) ? &pExportInfo->areaBox : NULL;
  246.  
  247.         AABB boxWS = GetBBox();
  248.  
  249.         if (pAreaBox && !Overlap::AABB_AABB(boxWS, *pAreaBox))
  250.                 return 0;
  251.  
  252.         if (pData)
  253.         {
  254.                 // get node data
  255.                 STerrainNodeChunk* pCunk = (STerrainNodeChunk*)pData;
  256.                 pCunk->nChunkVersion = TERRAIN_NODE_CHUNK_VERSION;
  257. #ifdef SEG_WORLD
  258.                 pCunk->boxHeightmap = this->m_boxHeigtmapLocal;
  259. #else
  260.                 pCunk->boxHeightmap = boxWS;
  261. #endif
  262.                 pCunk->bHasHoles = m_bHasHoles;
  263.                 pCunk->fOffset = m_rangeInfo.fOffset;
  264.                 pCunk->fRange = m_rangeInfo.fRange;
  265.                 pCunk->nSize = m_rangeInfo.nSize;
  266.                 pCunk->nSurfaceTypesNum = m_lstSurfaceTypeInfo.Count();
  267.  
  268.                 SwapEndian(*pCunk, eEndian);
  269.                 UPDATE_PTR_AND_SIZE(pData, nDataSize, sizeof(STerrainNodeChunk));
  270.  
  271.                 // get heightmap data
  272.                 AddToPtr(pData, nDataSize, m_rangeInfo.pHMData, m_rangeInfo.nSize * m_rangeInfo.nSize, eEndian, true);
  273.                 //              memcpy(pData, m_rangeInfo.pHMData, nBlockSize);
  274.                 //      UPDATE_PTR_AND_SIZE(pData,nDataSize,nBlockSize);
  275.  
  276.                 // get heightmap error data
  277.                 AddToPtr(pData, nDataSize, m_pGeomErrors, GetTerrain()->m_nUnitsToSectorBitShift, eEndian);
  278.                 //              memcpy(pData, m_pGeomErrors, GetTerrain()->m_nUnitsToSectorBitShift*sizeof(m_pGeomErrors[0]));
  279.                 //      UPDATE_PTR_AND_SIZE(pData,nDataSize,GetTerrain()->m_nUnitsToSectorBitShift*sizeof(m_pGeomErrors[0]));
  280.  
  281.                 // get used surf types
  282.                 CRY_ASSERT(m_lstSurfaceTypeInfo.Count() <= SRangeInfo::e_max_surface_types);
  283.                 uint8 arrTmp[SRangeInfo::e_max_surface_types] = { SRangeInfo::e_index_undefined };
  284.                 for (int i = 0; i < SRangeInfo::e_max_surface_types && i < m_lstSurfaceTypeInfo.Count(); i++)
  285.                         arrTmp[i] = m_lstSurfaceTypeInfo[i].pSurfaceType->ucThisSurfaceTypeId;
  286.  
  287.                 // For a leaf sector, store its surface type palette.
  288.                 if (m_rangeInfo.pSTPalette)
  289.                 {
  290.                         assert(m_rangeInfo.pSTPalette[SRangeInfo::e_index_hole] == SRangeInfo::e_hole);
  291.  
  292.                         // To ensure correct reconstruction of the sector's palette on loading, all entries present in the palette
  293.                         // must be *in the beginning* of arrTmp, *in the same order as in the palette*. The palette should not contain
  294.                         // any entries that are not included in arrTmp.
  295.  
  296.                         // Check which palette entries are actually used in the sector. Editing can leave unused palette entries.
  297.                         // The check omits the last row and the last column of the sector (m_lstSurfaceTypeInfo does not include them).
  298.                         int nDataCount = m_rangeInfo.nSize * (m_rangeInfo.nSize - 1);
  299.                         int nUsedPaletteEntrisCount = 0;
  300.                         bool UsedPaletteEntries[SRangeInfo::e_palette_size];
  301.                         memset(UsedPaletteEntries, 0, sizeof(UsedPaletteEntries));
  302.                         for (int i = 0; i < nDataCount; i++)
  303.                         {
  304.                                 if ((i + 1) % m_rangeInfo.nSize) // Ignore sector's last column
  305.                                         UsedPaletteEntries[m_rangeInfo.GetSurfaceTypeByIndex(i)] = true;
  306.                         }
  307.  
  308.                         // Clear any palette entries whose indices do not occur in the data (set them to 127). They are not present in
  309.                         // m_lstSurfaceTypeInfo/arrTmp, so they cannot be stored (and there is no reason to store them anyway).
  310.                         for (int i = 0; i < SRangeInfo::e_index_undefined; i++)
  311.                         {
  312.                                 if (!UsedPaletteEntries[i])
  313.                                         m_rangeInfo.pSTPalette[i] = SRangeInfo::e_undefined;
  314.                                 else
  315.                                 {
  316.                                         assert(m_rangeInfo.pSTPalette[i] != SRangeInfo::e_hole);
  317.                                         nUsedPaletteEntrisCount++;
  318.                                 }
  319.                         }
  320.  
  321.                         assert(nUsedPaletteEntrisCount <= m_lstSurfaceTypeInfo.Count());
  322.  
  323.                         // Reorder arrTmp so that the palette's entries are in the correct order in the beginning of the list.
  324.                         int nTargetListEntry = 0;
  325.                         for (int i = 0; i < SRangeInfo::e_index_undefined; i++)
  326.                         {
  327.                                 if (UsedPaletteEntries[i])
  328.                                 {
  329.                                         assert(m_rangeInfo.pSTPalette[i] != SRangeInfo::e_hole);
  330.                                         // Take the current palette entry and find the corresponding entry in arrTmp.
  331.                                         int nCurrentListEntry = -1;
  332.                                         for (int j = 0; nCurrentListEntry < 0 && j < SRangeInfo::e_index_undefined && j < m_lstSurfaceTypeInfo.Count(); j++)
  333.                                         {
  334.                                                 if (arrTmp[j] == m_rangeInfo.pSTPalette[i])
  335.                                                         nCurrentListEntry = j;
  336.                                         }
  337.  
  338.                                         // Swap the entries in arrTmp to move the entry where we want it.
  339.                                         assert(nCurrentListEntry >= 0);
  340.                                         PREFAST_ASSUME(nCurrentListEntry >= 0);
  341.                                         if (nCurrentListEntry != nTargetListEntry)
  342.                                                 std::swap(arrTmp[nCurrentListEntry], arrTmp[nTargetListEntry]);
  343.                                         nTargetListEntry++;
  344.                                 }
  345.                         }
  346.                 }
  347.  
  348.                 AddToPtr(pData, nDataSize, arrTmp, m_lstSurfaceTypeInfo.Count(), eEndian, true);
  349.                 //              memcpy(pData, arrTmp, m_lstSurfaceTypeInfo.Count()*sizeof(uint8));
  350.                 //      UPDATE_PTR_AND_SIZE(pData,nDataSize,m_lstSurfaceTypeInfo.Count()*sizeof(uint8));
  351.         }
  352.         else // just count size
  353.         {
  354.                 nDataSize += sizeof(STerrainNodeChunk);
  355.                 nDataSize += m_rangeInfo.nSize * m_rangeInfo.nSize * sizeof(m_rangeInfo.pHMData[0]);
  356.                 while (nDataSize & 3)
  357.                         nDataSize++;
  358.                 nDataSize += GetTerrain()->m_nUnitsToSectorBitShift * sizeof(m_pGeomErrors[0]);
  359.                 nDataSize += m_lstSurfaceTypeInfo.Count() * sizeof(uint8);
  360.                 while (nDataSize & 3)
  361.                         nDataSize++;
  362.         }
  363.  
  364.         // count number of nodes saved
  365.         int nNodesNum = 1;
  366.  
  367.         // process childs
  368.         for (int i = 0; m_pChilds && i < 4; i++)
  369.                 nNodesNum += m_pChilds[i].GetData(pData, nDataSize, eEndian, pExportInfo);
  370.  
  371.         return nNodesNum;
  372. }
  373.  
downloadterrain_node_compile.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