BVB Source Codes

CRYENGINE Show SegmentedWorld.cpp Source code

Return Download CRYENGINE: download SegmentedWorld.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:   SegmentedWorld.cpp
  5. //  Version:     v1.00
  6. //  Created:     4/11/2011 by Allen Chen
  7. //  Compilers:   Visual Studio.NET
  8. //  Description:
  9. // -------------------------------------------------------------------------
  10. //  History:
  11. //
  12. ////////////////////////////////////////////////////////////////////////////
  13.  
  14. #include "StdAfx.h"
  15. #include "SegmentedWorld.h"
  16. #include "IVehicleSystem.h"
  17. #include <CryRenderer/IRenderAuxGeom.h>
  18. #include "CryActionCVars.h"
  19.  
  20. #define MINIMUM_GRID_SIZE 3
  21. #define MAXIMUM_GRID_SIZE 32
  22.  
  23. string CSegmentedWorld::s_levelName;
  24. XmlNodeRef CSegmentedWorld::s_levelSurfaceTypes;
  25. XmlNodeRef CSegmentedWorld::s_levelObjects;
  26.  
  27. CSegmentedWorld::CSegmentedWorld()
  28.         : m_segmentSizeMeters(0)
  29.         , m_invSegmentSizeMeters(0.0f)
  30.         , m_pPoolAllocator(nullptr)
  31.         , m_bInitialWorldReady(false)
  32. {
  33.         if (gEnv->pGameFramework)
  34.         {
  35.                 CRY_ASSERT_MESSAGE(gEnv->pGameFramework->GetILevelSystem(), "Unable to register as levelsystem listener!");
  36.                 if (gEnv->pGameFramework->GetILevelSystem())
  37.                 {
  38.                         gEnv->pGameFramework->GetILevelSystem()->AddListener(this);
  39.                 }
  40.         }
  41. }
  42.  
  43. CSegmentedWorld::~CSegmentedWorld()
  44. {
  45.         SAFE_DELETE(m_pPoolAllocator);
  46.  
  47.         if (gEnv->pGameFramework)
  48.         {
  49.                 if (gEnv->pGameFramework->GetILevelSystem())
  50.                         gEnv->pGameFramework->GetILevelSystem()->RemoveListener(this);
  51.         }
  52. }
  53.  
  54. void CSegmentedWorld::OnLoadingStart(ILevelInfo* pLevel)
  55. {
  56.         if (!pLevel)
  57.                 return;
  58.  
  59.         Reset();
  60.  
  61.         string levelPath = string(pLevel->GetPath()) + "/";
  62.         XmlNodeRef levelInfoNode = GetISystem()->LoadXmlFromFile(levelPath + "segmentedlevelinfo.xml");
  63.         if (levelInfoNode)
  64.         {
  65.                 bool bEntitiesUseGUIDs = false;
  66.                 levelInfoNode->getAttr("SegmentedWorldSizeMeters", m_segmentSizeMeters);
  67.                 levelInfoNode->getAttr("SegmentedWorldMinX", m_segmentsMin.x);
  68.                 levelInfoNode->getAttr("SegmentedWorldMinY", m_segmentsMin.y);
  69.                 levelInfoNode->getAttr("SegmentedWorldMaxX", m_segmentsMax.x);
  70.                 levelInfoNode->getAttr("SegmentedWorldMaxY", m_segmentsMax.y);
  71.                 levelInfoNode->getAttr("EntitiesUseGUIDs", bEntitiesUseGUIDs);
  72.  
  73.                 bool bInvalidInput = m_segmentsMin.x > m_segmentsMax.x || m_segmentsMin.y > m_segmentsMax.y;
  74. #ifdef DEDICATED_SERVER
  75.                 bInvalidInput |= bEntitiesUseGUIDs;
  76. #else
  77.                 if (gEnv->bMultiplayer)
  78.                         bInvalidInput |= bEntitiesUseGUIDs;
  79. #endif
  80.  
  81.                 if (bInvalidInput)
  82.                 {
  83.                         CRY_ASSERT(false);
  84.                         GameWarning("Invalid segmented world bounds info");
  85.                         gEnv->p3DEngine->SetSegmentsManager(0);
  86.                         return;
  87.                 }
  88.  
  89.                 s_levelName = pLevel->GetName();
  90.                 s_levelName.MakeLower();
  91.  
  92.                 XmlNodeRef xmlLevelData = gEnv->pSystem->LoadXmlFromFile(levelPath + "leveldata.xml");
  93.                 s_levelSurfaceTypes = xmlLevelData->findChild("SurfaceTypes");
  94.  
  95.                 XmlNodeRef xmlMission = gEnv->pSystem->LoadXmlFromFile(levelPath + pLevel->GetDefaultGameType()->xmlFile);
  96.                 s_levelObjects = xmlMission->findChild("Objects");
  97.  
  98.                 gEnv->p3DEngine->SetSegmentsManager(this);
  99.                 gEnv->pEntitySystem->SetEntitiesUseGUIDs(bEntitiesUseGUIDs);
  100.  
  101.                 m_invSegmentSizeMeters = 1.0f / m_segmentSizeMeters;
  102.  
  103.                 m_neededSegmentsMin.x = 0;
  104.                 m_neededSegmentsMin.y = 0;
  105.  
  106.                 int gridSize = CCryActionCVars::Get().sw_gridSize;
  107.                 m_neededSegmentsMax.x = gridSize;
  108.                 m_neededSegmentsMax.y = gridSize;
  109.  
  110.                 m_neededSegmentsHalfSizeMeters.x = (m_neededSegmentsMax.x - m_neededSegmentsMin.x) * m_segmentSizeMeters * 0.5f;
  111.                 m_neededSegmentsHalfSizeMeters.y = (m_neededSegmentsMax.y - m_neededSegmentsMin.y) * m_segmentSizeMeters * 0.5f;
  112.  
  113.                 assert(m_pPoolAllocator->GetTotalMemory().nAlloc == 0);
  114.         }
  115.         else
  116.         {
  117.                 gEnv->p3DEngine->SetSegmentsManager(0);
  118.                 gEnv->pEntitySystem->SetEntitiesUseGUIDs(false);
  119.         }
  120. }
  121.  
  122. void CSegmentedWorld::OnLoadingComplete(ILevelInfo* pLevel)
  123. {
  124.         if (!pLevel || !s_levelObjects)
  125.                 return;
  126.  
  127. #ifndef DEDICATED_SERVER
  128.         // set all the global entities invisible
  129.         EntityId id = 0;
  130.         EntityGUID guid = 0;
  131.         IEntity* pEntity = NULL;
  132.  
  133.         for (int i = 0; i < s_levelObjects->getChildCount(); i++)
  134.         {
  135.                 XmlNodeRef xmlEntity = s_levelObjects->getChild(i);
  136.                 if (xmlEntity->getAttr("EntityGuid", guid))
  137.                 {
  138.                         id = gEnv->pEntitySystem->FindEntityByGuid(guid);
  139.                         pEntity = gEnv->pEntitySystem->GetEntity(id);
  140.  
  141.                         if (pEntity)
  142.                         {
  143.                                 pEntity->Invisible(true);
  144.                         }
  145.                 }
  146.         }
  147. #endif
  148. }
  149.  
  150. void CSegmentedWorld::OnUnloadComplete(ILevelInfo* pLevel)
  151. {
  152.         if (!pLevel)
  153.                 return;
  154.  
  155.         gEnv->p3DEngine->SetSegmentsManager(0);
  156. }
  157.  
  158. void CSegmentedWorld::Reset()
  159. {
  160.         int& gridSize = CCryActionCVars::Get().sw_gridSize;
  161.         gridSize = CLAMP(gridSize, MINIMUM_GRID_SIZE, MAXIMUM_GRID_SIZE);
  162.  
  163.         m_arrSegments.clear();
  164.  
  165.         m_bInitialWorldReady = false;
  166.         m_accSegmentOffset = Vec2i(ZERO);
  167.         m_segmentsMin = Vec2i(ZERO);
  168.         m_segmentsMax = Vec2i(ZERO);
  169.  
  170.         SAFE_DELETE(m_pPoolAllocator);
  171.         int poolSize = gridSize * gridSize * 2;
  172.         m_pPoolAllocator = new stl::TPoolAllocator<CSegmentNode>(stl::FHeap().PageSize(poolSize));
  173.  
  174.         s_levelSurfaceTypes = NULL;
  175.         s_levelObjects = NULL;
  176. }
  177.  
  178. CSegmentNode* CSegmentedWorld::PreloadSegment(int wx, int wy)
  179. {
  180.         CSegmentNode* pSeg = NULL;
  181.  
  182.         if (pSeg = FindSegmentByWorldCoords(wx, wy))
  183.                 return pSeg;
  184.  
  185.         assert(m_pPoolAllocator);
  186.         void* pAlloc = m_pPoolAllocator->Allocate();
  187.  
  188.         pSeg = new(pAlloc) CSegmentNode(this, wx, wy, wx - m_neededSegmentsMin.x, wy - m_neededSegmentsMin.y);
  189.  
  190.         assert(pSeg);
  191.         m_arrSegments.push_back(pSeg);
  192.  
  193.         return pSeg;
  194. }
  195.  
  196. Vec2i CalcSWMove(int lx, int ly, const Vec2i& vMin, const Vec2i& vMax, int iThreshold)
  197. {
  198.         Vec2i vCenter((vMax.x - vMin.x) / 2, (vMax.y - vMin.y) / 2);
  199.         Vec2i vThreshold(iThreshold, iThreshold);
  200.         Vec2i vMinOK = vCenter - vThreshold;
  201.         Vec2i vMaxOK = vCenter + vThreshold;
  202.  
  203.         Vec2i vOfs;
  204.  
  205.         // handle odd sized rectangles as well
  206.         bool xOdd = (vMax.x - vMin.x) % 2 == 1;
  207.         bool yOdd = (vMax.y - vMin.y) % 2 == 1;
  208.  
  209.         if (xOdd && lx <= vMinOK.x)
  210.                 vOfs.x = lx - vMinOK.x - 1; // negative, move left
  211.         else if (!xOdd && lx < vMinOK.x)
  212.                 vOfs.x = lx - vMinOK.x; // negative, move left
  213.         else if (lx >= vMaxOK.x)
  214.                 vOfs.x = lx - vMaxOK.x + 1; // positive, move right
  215.         else
  216.                 vOfs.x = 0;
  217.  
  218.         if (yOdd && ly <= vMinOK.y)
  219.                 vOfs.y = ly - vMinOK.y - 1; // negative, move left
  220.         else if (!yOdd && ly < vMinOK.y)
  221.                 vOfs.y = ly - vMinOK.y; // negative, move up
  222.         else if (ly >= vMaxOK.y)
  223.                 vOfs.y = ly - vMaxOK.y + 1; // positive, move down
  224.         else
  225.                 vOfs.y = 0;
  226.  
  227.         return vOfs;
  228. }
  229.  
  230. void CSegmentedWorld::UpdateActiveSegmentBound(const Vec2i& offset)
  231. {
  232.         m_neededSegmentsMin += offset;
  233.         m_neededSegmentsMax += offset;
  234.         m_accSegmentOffset += offset;
  235.  
  236.         Vec2i activeSegmentSize = m_neededSegmentsMax - m_neededSegmentsMin;
  237.         int xAdj = (activeSegmentSize.x % 2 == 1) ? 0 : 1;
  238.         int yAdj = (activeSegmentSize.y % 2 == 1) ? 0 : 1;
  239.         m_neededSegmentsCenter.x = m_neededSegmentsMin.x + activeSegmentSize.x / 2 - xAdj;
  240.         m_neededSegmentsCenter.y = m_neededSegmentsMin.y + activeSegmentSize.y / 2 - yAdj;
  241. }
  242.  
  243. bool CSegmentedWorld::LoadInitialWorld(const Vec3& pos)
  244. {
  245.         if (m_bInitialWorldReady)
  246.                 return true;
  247.  
  248.         Vec2i posSS = WorldToGridPosition(pos);
  249.         Vec2i vOfs = CalcSWMove(posSS.x, posSS.y, m_neededSegmentsMin, m_neededSegmentsMax, 1);
  250.  
  251.         UpdateActiveSegmentBound(vOfs);
  252.  
  253.         ForceLoadSegments(m_neededSegmentsMin, m_neededSegmentsMax, ISegmentsManager::slfAll);
  254.         AdjustGlobalObjects();
  255.  
  256.         return true;
  257. }
  258.  
  259. void CSegmentedWorld::ForceLoadSegments(const Vec2i& segmentsMin, const Vec2i& segmentsMax, unsigned int flags)
  260. {
  261.         assert(segmentsMin.x < segmentsMax.x && segmentsMin.y < segmentsMax.y);
  262.  
  263.         gEnv->p3DEngine->SetSegmentOperationInProgress(true);
  264.  
  265.         for (int wy = segmentsMin.y; wy < segmentsMax.y; ++wy)
  266.         {
  267.                 for (int wx = segmentsMin.x; wx < segmentsMax.x; ++wx)
  268.                 {
  269.                         CSegmentNode* pSeg = PreloadSegment(wx, wy);
  270.                         pSeg->ForceLoad(flags);
  271.                 }
  272.         }
  273.  
  274.         // CS - update connections..
  275.         gEnv->p3DEngine->GetIVisAreaManager()->UpdateConnections();
  276.         gEnv->p3DEngine->SetSegmentOperationInProgress(false);
  277. }
  278.  
  279. void CSegmentedWorld::DeleteSegment(int wx, int wy)
  280. {
  281.         for (int i = 0; i < m_arrSegments.size(); ++i)
  282.         {
  283.                 CSegmentNode* pSeg = m_arrSegments[i];
  284.                 if (pSeg->m_wx == wx && pSeg->m_wy == wy)
  285.                 {
  286.                         m_arrSegments.erase(m_arrSegments.begin() + i);
  287.  
  288.                         pSeg->~CSegmentNode();
  289.                         m_pPoolAllocator->Deallocate(pSeg);
  290.                         return;
  291.                 }
  292.         }
  293. }
  294.  
  295. bool CSegmentedWorld::NeedToUpdateSegment(int wx, int wy)
  296. {
  297.         CSegmentNode* pSeg = FindSegmentByWorldCoords(wx, wy);
  298.         if (!pSeg) return true;
  299.  
  300.         return !pSeg->StreamingFinished();
  301. }
  302.  
  303. bool CSegmentedWorld::MoveToSegment(int x, int y)
  304. {
  305.         Vec3 wPos = GridToWorldPosition(x, y);
  306.         char str[256];
  307.         cry_sprintf(str, "goto %f %f %f", wPos.x, wPos.y, wPos.z);
  308.         gEnv->pConsole->ExecuteString(str, true);
  309.  
  310.         return true;
  311. }
  312.  
  313. Vec2i CSegmentedWorld::SelectSegmentToUpdate(const Vec2i& focalPointWC)
  314. {
  315.         // Select the segment closest to the player to update
  316.         Vec2i segmentToUpdateWC = Vec2i(0, 0);
  317.         int segmentToUpdateDistance = INT_MAX;
  318.         for (int x = m_neededSegmentsMin.x; x < m_neededSegmentsMax.x; ++x)
  319.         {
  320.                 for (int y = m_neededSegmentsMin.y; y < m_neededSegmentsMax.y; ++y)
  321.                 {
  322.                         if (!NeedToUpdateSegment(x, y)) continue;
  323.                         Vec2i wc = Vec2i(x, y);
  324.                         int distance = (focalPointWC - wc).GetLength2();
  325.                         if (distance < segmentToUpdateDistance)
  326.                         {
  327.                                 segmentToUpdateWC = wc;
  328.                                 segmentToUpdateDistance = distance;
  329.                         }
  330.                 }
  331.                 // Also consider all segments outside the boundaries
  332.                 for (int i = 0; i < m_arrSegments.size(); ++i)
  333.                 {
  334.                         Vec2i wc = Vec2i(m_arrSegments[i]->m_wx, m_arrSegments[i]->m_wy);
  335.                         if (wc.x < m_neededSegmentsMin.x || wc.x >= m_neededSegmentsMax.x ||
  336.                             wc.y < m_neededSegmentsMin.y || wc.y >= m_neededSegmentsMax.y)
  337.                         {
  338.                                 int distance = (focalPointWC - wc).GetLength2();
  339.                                 if (distance < segmentToUpdateDistance)
  340.                                 {
  341.                                         segmentToUpdateWC = wc;
  342.                                         segmentToUpdateDistance = distance;
  343.                                 }
  344.                         }
  345.                 }
  346.         }
  347.         return segmentToUpdateWC;
  348. }
  349.  
  350. void CSegmentedWorld::AdjustGlobalObjects()
  351. {
  352.         EntityId id = 0;
  353.         EntityGUID guid = 0;
  354.         IEntity* pEntity = NULL;
  355.         Vec3 offset = GridToWorldPosition(-m_neededSegmentsMin);
  356.  
  357.         for (int i = 0; i < s_levelObjects->getChildCount(); i++)
  358.         {
  359.                 XmlNodeRef xmlEntity = s_levelObjects->getChild(i);
  360.                 if (xmlEntity->getAttr("EntityGuid", guid))
  361.                 {
  362.                         id = gEnv->pEntitySystem->FindEntityByGuid(guid);
  363.                         pEntity = gEnv->pEntitySystem->GetEntity(id);
  364.  
  365.                         if (pEntity)
  366.                         {
  367.                                 pEntity->SetPos(pEntity->GetPos() + offset);
  368.                         }
  369.                 }
  370.         }
  371. }
  372.  
  373. void CSegmentedWorld::PostUpdate()
  374. {
  375.         if (gEnv->p3DEngine->GetSegmentsManager() != this)
  376.                 return;
  377.  
  378.         gEnv->p3DEngine->GetIVisAreaManager()->ReleaseInactiveSegments();
  379.         gEnv->p3DEngine->GetITerrain()->ReleaseInactiveSegments();
  380.  
  381.         // correct the player's position after specified by flownode
  382.         if (!m_bInitialWorldReady)
  383.         {
  384.                 IActor* pClientPlayer = gEnv->pGameFramework->GetClientActor();
  385.                 if (!pClientPlayer || pClientPlayer->IsDead())
  386.                         return;
  387.  
  388.                 // set player position as our world focal point
  389.                 m_worldFocalPoint = pClientPlayer->GetEntity()->GetWorldPos();
  390.  
  391.                 GetISystem()->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_SW_FORCE_LOAD_START, 0, 0);
  392.  
  393.                 LoadInitialWorld(m_worldFocalPoint);
  394.  
  395.                 Vec3 offset = GridToWorldPosition(-m_neededSegmentsMin);
  396.                 pClientPlayer->GetEntity()->SetPos(m_worldFocalPoint + offset);
  397.  
  398.                 GetISystem()->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_SW_FORCE_LOAD_END, 0, 0);
  399.  
  400.                 m_bInitialWorldReady = true;
  401.         }
  402. }
  403.  
  404. void CSegmentedWorld::Update()
  405. {
  406.         if (gEnv->p3DEngine->GetSegmentsManager() != this)
  407.                 return;
  408.  
  409.         IActor* pClientPlayer = gEnv->pGameFramework->GetClientActor();
  410.         if (!pClientPlayer || pClientPlayer->IsDead() || !m_bInitialWorldReady)
  411.                 return;
  412.  
  413.         // set player position as our world focal point
  414.         m_worldFocalPoint = pClientPlayer->GetEntity()->GetWorldPos();
  415.  
  416.         // player position in grid space
  417. #if USE_RELATIVE_COORD
  418.         m_gridFocalPointLC = WorldToGridPosition(m_worldFocalPoint);
  419.         m_gridFocalPointWC = m_neededSegmentsMin + m_gridFocalPointLC;
  420. #else
  421.         m_gridFocalPointWC = WorldToGridPosition(m_worldFocalPoint);
  422.         m_gridFocalPointLC = m_gridFocalPointWC - m_accSegmentOffset;
  423. #endif
  424.  
  425.         int iThreshold = 1;//gEnv->pConsole->GetCVar("sw_autoMove")->GetIVal();
  426.         if (iThreshold > 0)
  427.         {
  428.                 Vec2i vOfs = CalcSWMove(m_gridFocalPointLC.x, m_gridFocalPointLC.y, m_neededSegmentsMin, m_neededSegmentsMax, iThreshold);
  429.  
  430.                 if (vOfs.x < -1) vOfs.x = -1;
  431.                 if (vOfs.x > +1) vOfs.x = +1;
  432.                 if (vOfs.y < -1) vOfs.y = -1;
  433.                 if (vOfs.y > +1) vOfs.y = +1;
  434.  
  435.                 UpdateActiveSegmentBound(vOfs);
  436.  
  437. #if USE_RELATIVE_COORD
  438.                 // offset position for existing objects
  439.                 Vec3 offset((float)(-vOfs.x * m_segmentSizeMeters), (float)(-vOfs.y * m_segmentSizeMeters), 0);
  440.                 gEnv->pRenderer->OffsetPosition(offset);
  441.                 if (vOfs.x != 0 || vOfs.y != 0)
  442.                 {
  443.                         for (int i = 0; i < m_arrSegments.size(); i++)
  444.                         {
  445.                                 CSegmentNode* pSeg = m_arrSegments[i];
  446.                                 pSeg->SetLocalCoords(pSeg->m_wx - m_neededSegmentsMin.x, pSeg->m_wy - m_neededSegmentsMin.y);
  447.                         }
  448.  
  449.                         gEnv->p3DEngine->GetIVisAreaManager()->OffsetPosition(offset);
  450.  
  451.                         Vec3 entPos;
  452.                         IEntityItPtr pIt = gEnv->pEntitySystem->GetEntityIterator();
  453.                         while (IEntity* pEnt = pIt->Next())
  454.                         {
  455.                                 if (pEnt->GetParent() == 0)
  456.                                 {
  457.                                         entPos = pEnt->GetPos() + offset;
  458.                                         float xdiff = entPos.x - m_neededSegmentsHalfSizeMeters.x;
  459.                                         float ydiff = entPos.y - m_neededSegmentsHalfSizeMeters.y;
  460.                                         if (pEnt->GetPhysics() && (xdiff > m_neededSegmentsHalfSizeMeters.x || xdiff < -m_neededSegmentsHalfSizeMeters.x
  461.                                                                    || ydiff > m_neededSegmentsHalfSizeMeters.y || ydiff < -m_neededSegmentsHalfSizeMeters.y))
  462.                                         {
  463.                                                 pEnt->Invisible(true);
  464.                                         }
  465.                                         pEnt->SetPos(entPos, 0, true);
  466.                                 }
  467.  
  468.                                 if (IVehicle* pVehicle = gEnv->pGameFramework->GetIVehicleSystem()->GetVehicle(pEnt->GetId()))
  469.                                         pVehicle->OffsetPosition(offset);
  470.                         }
  471.  
  472.                         gEnv->p3DEngine->OffsetPosition(offset);
  473.  
  474.                         // Update focal points
  475.                         m_worldFocalPoint = pClientPlayer->GetEntity()->GetWorldPos();
  476.                         m_gridFocalPointLC = WorldToGridPosition(m_worldFocalPoint);
  477.                         m_gridFocalPointWC = m_neededSegmentsMin + m_gridFocalPointLC;
  478.  
  479.                         GetISystem()->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_SW_SHIFT_WORLD, (UINT_PTR)&offset, 0);
  480.                 }
  481. #endif
  482.         }
  483.  
  484.         gEnv->p3DEngine->SetSegmentOperationInProgress(true);
  485.         Vec2i wc = SelectSegmentToUpdate(m_gridFocalPointWC);
  486.         UpdateSegment(wc.x, wc.y);
  487.         gEnv->p3DEngine->SetSegmentOperationInProgress(false);
  488.  
  489.         // display debug info on screen
  490.         DrawDebugInfo();
  491. }
  492.  
  493. void CSegmentedWorld::UpdateSegment(int wx, int wy)
  494. {
  495.         CSegmentNode* pSeg = FindSegmentByWorldCoords(wx, wy);
  496.  
  497.         // check if segment is out of active boundaries
  498.         if (wx < m_neededSegmentsMin.x || wx >= m_neededSegmentsMax.x ||
  499.             wy < m_neededSegmentsMin.y || wy >= m_neededSegmentsMax.y)
  500.         {
  501.                 if (!pSeg)
  502.                         return;
  503.  
  504.                 DeleteSegment(wx, wy);
  505.                 pSeg->SetStatus(ESEG_IDLE);
  506.         }
  507.         else
  508.         {
  509.                 if (!pSeg)
  510.                 {
  511.                         // allocate segment if not exit
  512.                         pSeg = PreloadSegment(wx, wy);
  513.                         pSeg->SetStatus(ESEG_INIT);
  514.                 }
  515.                 else
  516.                 {
  517.                         // request to start streaming
  518.                         pSeg->SetStatus(ESEG_STREAM);
  519.                 }
  520.         }
  521.         assert(pSeg);
  522.         pSeg->Update();
  523. }
  524.  
  525. CSegmentNode* CSegmentedWorld::FindSegNodeByWorldPos(const Vec3& pos)
  526. {
  527.         Vec2i ptSS = WorldToGridPosition(pos);
  528. #if USE_RELATIVE_COORD
  529.         CSegmentNode* pSeg = FindSegmentByLocalCoords(ptSS.x, ptSS.y);
  530. #else
  531.         CSegmentNode* pSeg = FindSegmentByWorldCoords(ptSS.x, ptSS.y);
  532. #endif
  533.  
  534.         return pSeg;
  535. }
  536.  
  537. bool CSegmentedWorld::FindSegment(ITerrain* pTerrain, const Vec3& pt, int& nSID)
  538. {
  539. #if USE_RELATIVE_COORD
  540.         Vec2i ptSS = WorldToGridPosition(pt);
  541.         CSegmentNode* pSeg = FindSegmentByLocalCoords(ptSS.x, ptSS.y);
  542.         if (pSeg && pSeg->OffsetApplied(pSeg->m_wx - m_neededSegmentsMin.x, pSeg->m_wy - m_neededSegmentsMin.y))
  543.         {
  544.                 nSID = pSeg->m_nSID;
  545.         }
  546.         else
  547.         {
  548.                 nSID = -1;
  549.         }
  550. #else
  551.         Vec2i ptSS = WorldToGridPosition(pt);
  552.         CSegmentNode* pSeg = FindSegmentByWorldCoords(ptSS.x, ptSS.y);
  553.         if (pSeg)
  554.         {
  555.                 nSID = pSeg->m_nSID;
  556.         }
  557.         else
  558.         {
  559.                 nSID = -1;
  560.         }
  561. #endif
  562.         return true;
  563. }
  564.  
  565. bool CSegmentedWorld::FindSegmentCoordByID(int nSID, int& x, int& y)
  566. {
  567.         for (int i = 0; i < m_arrSegments.size(); ++i)
  568.                 if (m_arrSegments[i]->m_nSID == nSID)
  569.                 {
  570.                         x = m_arrSegments[i]->m_wx;
  571.                         y = m_arrSegments[i]->m_wy;
  572.                         return true;
  573.                 }
  574.         return false;
  575. }
  576.  
  577. bool CSegmentedWorld::IsInsideSegmentedWorld(const Vec3& pt)
  578. {
  579.         return pt.x >= 0 && pt.y >= 0 &&
  580.                pt.y < (m_neededSegmentsMax.x - m_neededSegmentsMin.x) * m_segmentSizeMeters &&
  581.                pt.x < (m_neededSegmentsMax.y - m_neededSegmentsMin.y) * m_segmentSizeMeters;
  582. }
  583.  
  584. void CSegmentedWorld::GetTerrainSizeInMeters(int& x, int& y)
  585. {
  586.         x = (m_neededSegmentsMax.x - m_neededSegmentsMin.x) * m_segmentSizeMeters;
  587.         y = (m_neededSegmentsMax.y - m_neededSegmentsMin.y) * m_segmentSizeMeters;
  588. }
  589.  
  590. CSegmentNode* CSegmentedWorld::FindSegmentByID(int nSID)
  591. {
  592.         for (int i = 0; i < m_arrSegments.size(); ++i)
  593.                 if (m_arrSegments[i]->m_nSID == nSID)
  594.                         return m_arrSegments[i];
  595.         return 0;
  596. }
  597.  
  598. CSegmentNode* CSegmentedWorld::FindSegmentByWorldCoords(int wx, int wy)
  599. {
  600.         for (int i = 0; i < m_arrSegments.size(); ++i)
  601.         {
  602.                 CSegmentNode* pSeg = m_arrSegments[i];
  603.                 if (pSeg->m_wx == wx && pSeg->m_wy == wy)
  604.                         return pSeg;
  605.         }
  606.         return 0;
  607. }
  608.  
  609. CSegmentNode* CSegmentedWorld::FindSegmentByLocalCoords(int lx, int ly)
  610. {
  611.         for (int i = 0; i < m_arrSegments.size(); ++i)
  612.         {
  613.                 CSegmentNode* pSeg = m_arrSegments[i];
  614.                 if (pSeg->m_lx == lx && pSeg->m_ly == ly)
  615.                         return pSeg;
  616.         }
  617.         return 0;
  618. }
  619.  
  620. bool CSegmentedWorld::PushEntityToSegment(unsigned int id, bool bLocal)
  621. {
  622.         bool bRet = false;
  623.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(id);
  624.         if (pEntity)
  625.         {
  626.                 Vec3 pos = pEntity->GetWorldPos();
  627.                 CSegmentNode* pSegNode = FindSegNodeByWorldPos(pos);
  628.                 if (pSegNode)
  629.                 {
  630.                         if (bLocal)
  631.                                 pSegNode->m_localEntities.push_back(pEntity);
  632.                         else
  633.                                 pSegNode->m_globalEntities.push_back(pEntity);
  634.  
  635.                         bRet = true;
  636.                 }
  637.  
  638.         }
  639.  
  640.         return bRet;
  641. }
  642.  
  643. void CSegmentedWorld::DrawDebugInfo()
  644. {
  645.         int debugInfo = CCryActionCVars::Get().sw_debugInfo;
  646.         if (!debugInfo || gEnv->IsDedicated())
  647.                 return;
  648.  
  649.         int width = gEnv->pRenderer->GetWidth();
  650.         int height = gEnv->pRenderer->GetHeight();
  651.         GetISystem()->GetIRenderer()->Set2DMode(true, width, height);
  652.  
  653.         static float debugGridSize = 16;
  654.         if (m_segmentsMax.x > 32)
  655.                 debugGridSize = 8;
  656.  
  657.         Vec2 debugTextOrigin(50, 50);
  658.         Vec2 debugGridOrigin(debugTextOrigin.x, debugTextOrigin.y + m_segmentsMax.y * debugGridSize);
  659.  
  660.         DrawSegmentGrid(debugGridOrigin, debugGridSize);
  661.         if (debugInfo == 2)
  662.                 PrintSegmentInfo(debugTextOrigin, debugGridSize);
  663.         else if (debugInfo == 3)
  664.                 PrintMemoryInfo(debugTextOrigin, debugGridSize);
  665.  
  666.         GetISystem()->GetIRenderer()->Set2DMode(false, width, height);
  667. }
  668.  
  669. void CSegmentedWorld::DrawSegmentGrid(const Vec2& origin, float size)
  670. {
  671.         IRenderAuxGeom* pAux = GetISystem()->GetIRenderer()->GetIRenderAuxGeom();
  672.  
  673.         float sx, sy, thickness = 1;
  674.         ColorB color;
  675.         for (int x = m_segmentsMin.x; x <= m_segmentsMax.x; ++x)
  676.         {
  677.                 for (int y = m_segmentsMin.y; y <= m_segmentsMax.y; ++y)
  678.                 {
  679.                         CSegmentNode* pSeg = FindSegmentByWorldCoords(x, y);
  680.                         color =
  681.                           pSeg == 0 ? Col_Gray :
  682.                           !pSeg->StreamingSucceeded() ? Col_Yellow :
  683.                           Col_Green;
  684.  
  685.                         sx = origin.x + (float)(x - m_segmentsMin.x) * size;
  686.                         sy = origin.y - (float)(y - m_segmentsMin.y) * size;
  687.  
  688.                         pAux->DrawLine(Vec3(sx, sy, 0), color, Vec3(sx + size - 1, sy, 0), color, thickness);
  689.                         pAux->DrawLine(Vec3(sx + size - 1, sy, 0), color, Vec3(sx + size - 1, sy - (size - 1), 0), color, thickness);
  690.                         pAux->DrawLine(Vec3(sx + size - 1, sy - (size - 1), 0), color, Vec3(sx, sy - (size - 1), 0), color, thickness);
  691.                         pAux->DrawLine(Vec3(sx, sy - (size - 1), 0), color, Vec3(sx, sy, 0), color, thickness);
  692.                 }
  693.         }
  694.  
  695.         bool xOdd = (m_neededSegmentsMax.x - m_neededSegmentsMin.x) % 2 == 1;
  696.         bool yOdd = (m_neededSegmentsMax.y - m_neededSegmentsMin.y) % 2 == 1;
  697.         int xThreshold = xOdd ? 1 : 2;
  698.         int yThreshold = yOdd ? 1 : 2;
  699.         color = Col_Blue;
  700.         thickness = 2;
  701.         sx = origin.x + (float)(m_neededSegmentsCenter.x - m_segmentsMin.x) * size;
  702.         sy = origin.y - (float)(m_neededSegmentsCenter.y - m_segmentsMin.y) * size;
  703.         pAux->DrawLine(Vec3(sx, sy, 0), color, Vec3(sx + size * xThreshold - 1, sy, 0), color, thickness);
  704.         pAux->DrawLine(Vec3(sx + size * xThreshold - 1, sy, 0), color, Vec3(sx + size * xThreshold - 1, sy - (size * yThreshold - 1), 0), color, thickness);
  705.         pAux->DrawLine(Vec3(sx + size * xThreshold - 1, sy - (size * yThreshold - 1), 0), color, Vec3(sx, sy - (size * yThreshold - 1), 0), color, thickness);
  706.         pAux->DrawLine(Vec3(sx, sy - (size * xThreshold - 1), 0), color, Vec3(sx, sy, 0), color, 2);
  707.  
  708.         Vec3 playerGridPos = WorldToScreenPosition(m_worldFocalPoint);
  709.         playerGridPos.x -= m_segmentsMin.x;
  710.         playerGridPos.y -= m_segmentsMin.y;
  711. #if USE_RELATIVE_COORD
  712.         playerGridPos.x += m_neededSegmentsMin.x;
  713.         playerGridPos.y += m_neededSegmentsMin.y;
  714. #endif
  715.         playerGridPos *= size;
  716.         playerGridPos.y = -playerGridPos.y;
  717.  
  718.         playerGridPos += Vec3(origin.x, origin.y, 0);
  719.         pAux->DrawLine(playerGridPos - Vec3(2, 0, 0), Col_Red, playerGridPos + Vec3(2, 0, 0), Col_Red, 5);
  720.  
  721.         const CCamera& camera = gEnv->pRenderer->GetCamera();
  722.         {
  723.                 Vec3 lookDir = camera.GetViewdir();
  724.                 lookDir.y = -lookDir.y;
  725.                 lookDir.z = 0;
  726.                 lookDir.Normalize();
  727.  
  728.                 pAux->DrawLine(playerGridPos, Col_Red, playerGridPos + 10 * lookDir, Col_Red, 2);
  729.         }
  730. }
  731.  
  732. void CSegmentedWorld::PrintSegmentInfo(const Vec2& origin, float size)
  733. {
  734.         SDrawTextInfo ti;
  735.         int flags = eDrawText_FixedSize | eDrawText_2D | eDrawText_Monospace;
  736.  
  737.         Vec3 step(0, 16, 0);
  738.         Vec3 pos(origin.x, origin.y, 1);
  739.         pos.x += m_segmentsMax.x * size + 50;
  740.  
  741.         Vec3 worldPosLC, worldPosWC;
  742. #if USE_RELATIVE_COORD
  743.         float scale = 1.5f;
  744.         IRenderAuxText::DrawText(pos, scale, NULL, flags, string("Use Relative Coordinates"));
  745.         pos += step;
  746.         scale = 1.2f;
  747.         worldPosLC = m_worldFocalPoint;
  748.         worldPosWC = worldPosLC + GridToWorldPosition(m_neededSegmentsMin);
  749. #else
  750.         scale = 1.5f;
  751.         IRenderAuxText::DrawText(pos, scale, NULL, flags, string("Use Absolute Coordinates"));
  752.         pos += step;
  753.         ti.xscale = ti.yscale = 1.2f;
  754.         worldPosWC = m_worldFocalPoint;
  755.         worldPosLC = worldPosWC - GridToWorldPosition(m_neededSegmentsMin);
  756. #endif
  757.         pos += step;
  758.         IRenderAuxText::DrawText(pos, scale, NULL, flags, string().Format("Player Global World Position: %.2f, %.2f, %.2f", worldPosWC.x, worldPosWC.y, worldPosWC.z).c_str());
  759.         pos += step;
  760.         IRenderAuxText::DrawText(pos, scale, NULL, flags, string().Format("Player Global Grid Position: %d, %d", m_gridFocalPointWC.x, m_gridFocalPointWC.y).c_str());
  761.         pos += step;
  762.         IRenderAuxText::DrawText(pos, scale, NULL, flags, string().Format("Global Segments: (%d, %d), (%d,%d)", m_segmentsMin.x, m_segmentsMin.y, m_segmentsMax.x, m_segmentsMax.y).c_str());
  763. #ifdef _DEBUG
  764.         pos += step;
  765.         pos += step;
  766.         IRenderAuxText::DrawText(pos, scale, NULL, flags, string().Format("Player Local World Position: %.2f, %.2f, %.2f", worldPosLC.x, worldPosLC.y, worldPosLC.z).c_str());
  767.         pos += step;
  768.         IRenderAuxText::DrawText(pos, scale, NULL, flags, string().Format("Player Local Grid Position: %d, %d", m_gridFocalPointLC.x, m_gridFocalPointLC.y).c_str());
  769.         pos += step;
  770.         IRenderAuxText::DrawText(pos, scale, NULL, flags, string().Format("Active Segments: (%d, %d), (%d,%d)", m_neededSegmentsMin.x, m_neededSegmentsMin.y, m_neededSegmentsMax.x, m_neededSegmentsMax.y).c_str());
  771.         pos += step;
  772.         IRenderAuxText::DrawText(pos, scale, NULL, flags, string().Format("Active Segments Center: (%d, %d)", m_neededSegmentsCenter.x, m_neededSegmentsCenter.y).c_str());
  773. #endif
  774. }
  775.  
  776. void CSegmentedWorld::PrintMemoryInfo(const Vec2& origin, float size)
  777. {
  778.         Vec3 step(0, 16, 0);
  779.         Vec3 pos(origin.x, origin.y, 1);
  780.         pos.x += m_segmentsMax.x * size + 50;
  781.  
  782.         const stl::SPoolMemoryUsage memUsage = m_pPoolAllocator->GetTotalMemory();
  783.         IRenderAuxText::DrawText(pos, 1.2f, NULL, eDrawText_FixedSize | eDrawText_2D | eDrawText_Monospace, string().Format("Segment Heap: %d KB Used, %d KB Freed, %d KB Unused",
  784.                                                                  (int)(memUsage.nUsed >> 10), (int)(memUsage.nPoolFree() >> 10), (int)(memUsage.nNonPoolFree() >> 10)).c_str());
  785. }
  786.  
downloadSegmentedWorld.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