BVB Source Codes

CRYENGINE Show GeomCacheRenderNode.cpp Source code

Return Download CRYENGINE: download GeomCacheRenderNode.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:   GeomCacheRenderNode.cpp
  5. //  Created:     19/7/2012 by Axel Gneiting
  6. //  Description: Draws geometry caches
  7. // -------------------------------------------------------------------------
  8. //
  9. ////////////////////////////////////////////////////////////////////////////
  10.  
  11. #include "StdAfx.h"
  12. #include "xxhash.h"
  13.  
  14. #if defined(USE_GEOM_CACHES)
  15.  
  16.         #include "GeomCacheRenderNode.h"
  17.         #include "GeomCacheManager.h"
  18.         #include "MatMan.h"
  19.  
  20.         #include <CryThreading/IJobManager_JobDelegator.h>
  21.  
  22. DECLARE_JOB("GeomCacheUpdateMesh", TGeomCacheUpdateMeshJob, CGeomCacheRenderNode::UpdateMesh_JobEntry);
  23.  
  24. namespace
  25. {
  26. // Constants
  27. const float kDefaultMaxViewDist = 1000.0f;
  28. }
  29.  
  30. CGeomCacheRenderNode::CGeomCacheRenderNode()
  31.         : m_pGeomCache(NULL)
  32.         , m_playbackTime(0.0f)
  33.         , m_pPhysicalEntity(NULL)
  34.         , m_maxViewDist(kDefaultMaxViewDist)
  35.         , m_bBox(0.0f)
  36.         , m_currentAABB(0.0f)
  37.         , m_currentDisplayAABB(0.0f)
  38.         , m_standInVisible(eStandInType_None)
  39.         , m_pStandIn(NULL)
  40.         , m_pFirstFrameStandIn(NULL)
  41.         , m_pLastFrameStandIn(NULL)
  42.         , m_standInDistance(0.0f)
  43.         , m_streamInDistance(0.0f)
  44.         , m_bInitialized(false)
  45.         , m_bLooping(false)
  46.         , m_bIsStreaming(false)
  47.         , m_bFilledFrameOnce(false)
  48.         , m_bBoundsChanged(true)
  49.         , m_bDrawing(true)
  50.         , m_bTransformReady(true)
  51. {
  52.         GetInstCount(GetRenderNodeType())++;
  53.  
  54.         m_matrix.SetIdentity();
  55.         m_pMaterial = GetMatMan()->GetDefaultMaterial();
  56.  
  57.         SetRndFlags(ERF_HAS_CASTSHADOWMAPS, true);
  58.         SetRndFlags(ERF_CASTSHADOWMAPS, true);
  59. }
  60.  
  61. CGeomCacheRenderNode::~CGeomCacheRenderNode()
  62. {
  63.         GetInstCount(GetRenderNodeType())--;
  64.  
  65.         if (m_pGeomCache)
  66.         {
  67.                 m_pGeomCache->RemoveListener(this);
  68.         }
  69.  
  70.         Clear(true);
  71.         Get3DEngine()->FreeRenderNodeState(this);
  72. }
  73.  
  74. const char* CGeomCacheRenderNode::GetEntityClassName() const
  75. {
  76.         return "GeomCache";
  77. }
  78.  
  79. const char* CGeomCacheRenderNode::GetName() const
  80. {
  81.         if (m_pGeomCache)
  82.         {
  83.                 return m_pGeomCache->GetFilePath();
  84.         }
  85.  
  86.         return "GeomCacheNotSet";
  87. }
  88.  
  89. Vec3 CGeomCacheRenderNode::GetPos(bool bWorldOnly) const
  90. {
  91.         assert(bWorldOnly);
  92.         return m_matrix.GetTranslation();
  93. }
  94.  
  95. void CGeomCacheRenderNode::SetBBox(const AABB& bBox)
  96. {
  97.         m_bBox = bBox;
  98. }
  99.  
  100. const AABB CGeomCacheRenderNode::GetBBox() const
  101. {
  102.         return m_bBox;
  103. }
  104.  
  105. void CGeomCacheRenderNode::UpdateBBox()
  106. {
  107.         AABB newAABB;
  108.  
  109.         const Vec3 vCamPos = Get3DEngine()->GetRenderingCamera().GetPosition();
  110.         float distance = Distance::Point_Point(vCamPos, m_matrix.GetTranslation());
  111.  
  112.         const bool bGeomCacheLoaded = m_pGeomCache ? m_pGeomCache->IsLoaded() : false;
  113.  
  114.         const bool bAllowStandIn = GetCVars()->e_Lods != 0;
  115.         const bool bInStandInDistance = distance > m_standInDistance && bAllowStandIn;
  116.  
  117.         EStandInType selectedStandIn = SelectStandIn();
  118.         IStatObj* pStandIn = GetStandIn(selectedStandIn);
  119.  
  120.         if (pStandIn && (bInStandInDistance || !bGeomCacheLoaded))
  121.         {
  122.                 m_standInVisible = selectedStandIn;
  123.                 newAABB = pStandIn->GetAABB();
  124.         }
  125.         else
  126.         {
  127.                 m_standInVisible = eStandInType_None;
  128.                 newAABB = m_currentDisplayAABB;
  129.         }
  130.  
  131.         if (newAABB.min != m_currentAABB.min || newAABB.max != m_currentAABB.max)
  132.         {
  133.                 m_bBoundsChanged = true;
  134.                 m_currentAABB = newAABB;
  135.         }
  136.  
  137.         if (m_streamInDistance > 0.0f)
  138.         {
  139.                 m_bIsStreaming = distance <= m_streamInDistance;
  140.         }
  141. }
  142.  
  143. void CGeomCacheRenderNode::GetLocalBounds(AABB& bbox)
  144. {
  145.         bbox = m_currentAABB;
  146. }
  147.  
  148. void CGeomCacheRenderNode::OffsetPosition(const Vec3& delta)
  149. {
  150.         #ifdef SEG_WORLD
  151.         m_matrix.SetTranslation(m_matrix.GetTranslation() + delta);
  152.         UpdateBBox();
  153.         #endif
  154. }
  155.  
  156. bool CGeomCacheRenderNode::DidBoundsChange()
  157. {
  158.         bool bBoundsChanged = m_bBoundsChanged;
  159.  
  160.         if (bBoundsChanged)
  161.         {
  162.                 CalcBBox();
  163.         }
  164.  
  165.         m_bBoundsChanged = false;
  166.         return bBoundsChanged;
  167. }
  168.  
  169. /* Geom caches are rendered using a custom render element for performance reasons (CREGeomCache).
  170.  * We only call mfAdd once per material, so a lot of meshes can be rendered with just one CRenderObject in the render pipeline.
  171.  * Mesh and transform updates run asynchronously started from FillFrameAsync and are synchronized in the render thread (CREGeomCache::Update)
  172.  * Visible meshes are added to a SMeshRenderData vector in UpdateTransformsRec. The lists are rendered in CREGeomCache::mfDraw
  173.  * Downside is that meshes in the cache are not sorted by depth for transparency passes
  174.  */
  175. void CGeomCacheRenderNode::Render(const struct SRendParams& rendParams, const SRenderingPassInfo& passInfo)
  176. {
  177.         FUNCTION_PROFILER_3DENGINE;
  178.  
  179.         if (!m_bInitialized || !m_bDrawing || (m_renderMeshes.empty() && m_renderMeshUpdateContexts.empty())
  180.             || !m_pGeomCache || m_dwRndFlags & ERF_HIDDEN || !passInfo.RenderGeomCaches())
  181.         {
  182.                 return;
  183.         }
  184.  
  185.         m_pGeomCache->SetLastDrawMainFrameId(passInfo.GetMainFrameID());
  186.  
  187.         SRendParams drawParams = rendParams;
  188.  
  189.         drawParams.pMatrix = &m_matrix;
  190.  
  191.         static ICVar* pGraphicsPipelineCV = gEnv->pConsole->GetCVar("r_GraphicsPipeline");
  192.         static ICVar* pMotionVectorsCV = gEnv->pConsole->GetCVar("r_MotionVectors");
  193.  
  194.         switch (m_standInVisible)
  195.         {
  196.         case eStandInType_None:
  197.                 {
  198.         #ifndef _RELEASE
  199.                         if (GetCVars()->e_GeomCacheDebugDrawMode == 3)
  200.                         {
  201.                                 break;
  202.                         }
  203.         #endif
  204.  
  205.                         drawParams.pMaterial = m_pMaterial;
  206.  
  207.                         IRenderer* const pRenderer = GetRenderer();
  208.                         CRenderObject* pRenderObject = pRenderer->EF_GetObject_Temp(passInfo.ThreadID());
  209.  
  210.                         if (pRenderObject)
  211.                         {
  212.                                 FillRenderObject(drawParams, passInfo, m_pMaterial, pRenderObject);
  213.  
  214.                                 if (m_pRenderElements.size() > 0 && passInfo.IsGeneralPass())
  215.                                 {
  216.                                         // Only need to call this once because SRenderObjData::m_pInstance is the same for all of them
  217.                                         m_pRenderElements.begin()->second.m_pRenderElement->SetupMotionBlur(pRenderObject, passInfo);
  218.                                 }
  219.  
  220.                                 for (TRenderElementMap::iterator iter = m_pRenderElements.begin(); iter != m_pRenderElements.end(); ++iter)
  221.                                 {
  222.                                         const uint materialId = iter->first;
  223.                                         CREGeomCache* pCREGeomCache = iter->second.m_pRenderElement;
  224.  
  225.                                         SShaderItem& shaderItem = m_pMaterial->GetShaderItem(materialId);
  226.                                         const int afterWater = rendParams.nAfterWater;
  227.  
  228.                                         if (pGraphicsPipelineCV->GetIVal() == 0)
  229.                                         {
  230.                                                 pRenderer->EF_AddEf(pCREGeomCache, shaderItem, pRenderObject, passInfo, EFSLIST_GENERAL, afterWater);
  231.                                         }
  232.                                         else
  233.                                         {
  234.                                                 for (auto& meshData : *(pCREGeomCache->GetMeshFillDataPtr()))
  235.                                                 {
  236.                                                         if (meshData.m_pRenderMesh == nullptr)
  237.                                                                 continue;
  238.  
  239.                                                         for (auto& chunk : meshData.m_pRenderMesh->GetChunks())
  240.                                                         {
  241.                                                                 if (chunk.m_nMatID != materialId)
  242.                                                                 {
  243.                                                                         continue;
  244.                                                                 }
  245.  
  246.                                                                 CRenderElement* RESTRICT_POINTER pREMesh = chunk.pRE;
  247.                                                                 IRenderShaderResources* pR = shaderItem.m_pShaderResources;
  248.                                                                 IShader* RESTRICT_POINTER pS = shaderItem.m_pShader;
  249.  
  250.                                                                 for (auto& instance : meshData.m_instances)
  251.                                                                 {
  252.                                                                         if (pREMesh == NULL || pS == NULL || pR == NULL)
  253.                                                                                 continue;
  254.  
  255.                                                                         if (pS->GetFlags2() & EF2_NODRAW)
  256.                                                                                 continue;
  257.  
  258.                                                                         if (passInfo.IsShadowPass() && (pR->GetResFlags() & MTL_FLAG_NOSHADOW))
  259.                                                                                 continue;
  260.  
  261.                                                                         Matrix34A pieceMatrix = m_matrix * instance.m_matrix;
  262.  
  263.                                                                         AABB pieceWorldAABB;
  264.                                                                         pieceWorldAABB.SetTransformedAABB(pieceMatrix, instance.m_aabb);
  265.                                                                         if (!passInfo.GetCamera().IsAABBVisible_F(pieceWorldAABB))
  266.                                                                         {
  267.                                                                                 continue;
  268.                                                                         }
  269.  
  270.                                                                         auto pInstanceRenderObject = pRenderer->EF_DuplicateRO(pRenderObject, passInfo);
  271.                                                                         pInstanceRenderObject->m_II.m_Matrix = pieceMatrix;
  272.  
  273.                                                                         if (pMotionVectorsCV->GetIVal() && passInfo.IsGeneralPass() && ((pInstanceRenderObject->m_ObjFlags & FOB_DYNAMIC_OBJECT) != 0))
  274.                                                                         {
  275.                                                                                 if (SRenderObjData* pRenderObjData = pInstanceRenderObject->GetObjData())
  276.                                                                                 {
  277.                                                                                         uint8 hashableData[] =
  278.                                                                                         {
  279.                                                                                                 0,                                                                 0,          0, 0, 0, 0, 0, 0,
  280.                                                                                                 (uint8)std::distance(pCREGeomCache->GetMeshFillDataPtr()->begin(), &meshData),
  281.                                                                                                 (uint8)std::distance(meshData.m_pRenderMesh->GetChunks().begin(),  &chunk),
  282.                                                                                                 (uint8)std::distance(meshData.m_instances.begin(),                 &instance)
  283.                                                                                         };
  284.  
  285.                                                                                         memcpy(hashableData, pCREGeomCache, sizeof(pCREGeomCache));
  286.                                                                                         pRenderObjData->m_uniqueObjectId = static_cast<uintptr_t>(XXH64(hashableData, sizeof(hashableData), 0)) + reinterpret_cast<uintptr_t>(this);
  287.  
  288.                                                                                         pCREGeomCache->SetupMotionBlur(pInstanceRenderObject, passInfo);
  289.                                                                                 }
  290.                                                                         }
  291.  
  292.                                                                         pRenderer->EF_AddEf(pREMesh, shaderItem, pInstanceRenderObject, passInfo, EFSLIST_GENERAL, afterWater);
  293.                                                                 }
  294.                                                         }
  295.                                                 }
  296.                                         }
  297.                                 }
  298.                         }
  299.                         break;
  300.                 }
  301.         case eStandInType_Default:
  302.                 {
  303.                         // Override material if there stand in has a material that is not default
  304.                         IMaterial* pStandInMaterial = m_pStandIn->GetMaterial();
  305.                         drawParams.pMaterial = (pStandInMaterial && !pStandInMaterial->IsDefault()) ? pStandInMaterial : drawParams.pMaterial;
  306.  
  307.                         m_pStandIn->Render(drawParams, passInfo);
  308.                         break;
  309.                 }
  310.         case eStandInType_FirstFrame:
  311.                 {
  312.                         // Override material if there stand in has a material that is not default
  313.                         IMaterial* pStandInMaterial = m_pFirstFrameStandIn->GetMaterial();
  314.                         drawParams.pMaterial = (pStandInMaterial && !pStandInMaterial->IsDefault()) ? pStandInMaterial : drawParams.pMaterial;
  315.  
  316.                         m_pFirstFrameStandIn->Render(drawParams, passInfo);
  317.                         break;
  318.                 }
  319.         case eStandInType_LastFrame:
  320.                 {
  321.                         // Override material if there stand in has a material that is not default
  322.                         IMaterial* pStandInMaterial = m_pLastFrameStandIn->GetMaterial();
  323.                         drawParams.pMaterial = (pStandInMaterial && !pStandInMaterial->IsDefault()) ? pStandInMaterial : drawParams.pMaterial;
  324.  
  325.                         m_pLastFrameStandIn->Render(drawParams, passInfo);
  326.                         break;
  327.                 }
  328.         }
  329. }
  330.  
  331. void CGeomCacheRenderNode::SetMaterial(IMaterial* pMat)
  332. {
  333.         if (pMat)
  334.         {
  335.                 m_pMaterial = pMat;
  336.         }
  337.         else if (m_pGeomCache)
  338.         {
  339.                 IMaterial* pMaterial = m_pGeomCache->GetMaterial();
  340.                 m_pMaterial = pMaterial;
  341.         }
  342.         else
  343.         {
  344.                 m_pMaterial = GetMatMan()->GetDefaultMaterial();
  345.         }
  346.  
  347.         UpdatePhysicalMaterials();
  348. }
  349.  
  350. IMaterial* CGeomCacheRenderNode::GetMaterial(Vec3* pHitPos) const
  351. {
  352.         if (m_pMaterial)
  353.         {
  354.                 return m_pMaterial;
  355.         }
  356.         else if (m_pGeomCache)
  357.         {
  358.                 return m_pGeomCache->GetMaterial();
  359.         }
  360.  
  361.         return NULL;
  362. }
  363.  
  364. float CGeomCacheRenderNode::GetMaxViewDist()
  365. {
  366.         return m_maxViewDist;
  367. }
  368.  
  369. void CGeomCacheRenderNode::GetMemoryUsage(ICrySizer* pSizer) const
  370. {
  371.         SIZER_COMPONENT_NAME(pSizer, "GeomCache");
  372.         pSizer->AddObject(this, sizeof(*this));
  373. }
  374.  
  375. //////////////////////////////////////////////////////////////////////////
  376. void CGeomCacheRenderNode::UpdateStreamingPriority(const SUpdateStreamingPriorityContext& ctx)
  377. {
  378.         float fObjScale = max(0.001f, GetMatrix().GetColumn0().GetLength());
  379.         float fInvObjScale = 1.0f / fObjScale;
  380.         UpdateStreamableComponents(ctx.importance, ctx.distance, ctx.bFullUpdate, ctx.lod, fInvObjScale, ctx.bFullUpdate);
  381. }
  382.  
  383. void CGeomCacheRenderNode::SetMatrix(const Matrix34& matrix)
  384. {
  385.         m_matrix = matrix;
  386.         CalcBBox();
  387. }
  388.  
  389. void CGeomCacheRenderNode::CalcBBox()
  390. {
  391.         m_bBox = AABB(0.0f);
  392.  
  393.         if (!m_pGeomCache || !m_pGeomCache->IsValid())
  394.         {
  395.                 return;
  396.         }
  397.  
  398.         m_bBox.SetTransformedAABB(m_matrix, m_currentAABB);
  399. }
  400.  
  401. bool CGeomCacheRenderNode::LoadGeomCache(const char* sGeomCacheFileName)
  402. {
  403.         Clear(false);
  404.  
  405.         m_pGeomCache = static_cast<CGeomCache*>(Get3DEngine()->LoadGeomCache(sGeomCacheFileName));
  406.  
  407.         if (m_pGeomCache && !m_pGeomCache->IsValid())
  408.         {
  409.                 m_pGeomCache = NULL;
  410.         }
  411.  
  412.         if (m_pGeomCache)
  413.         {
  414.                 m_currentAABB = m_pGeomCache->GetAABB();
  415.                 m_bBoundsChanged = true;
  416.                 m_pMaterial = m_pGeomCache->GetMaterial();
  417.  
  418.                 const std::vector<SGeomCacheStaticNodeData>& staticNodeData = m_pGeomCache->GetStaticNodeData();
  419.                 m_nodeMatrices.resize(staticNodeData.size());
  420.                 uint currentNodeIndex = 0;
  421.                 InitTransformsRec(currentNodeIndex, staticNodeData, QuatTNS(IDENTITY));
  422.  
  423.                 m_pGeomCache->AddListener(this);
  424.  
  425.                 if (m_pGeomCache->IsLoaded())
  426.                 {
  427.                         return Initialize();
  428.                 }
  429.         }
  430.  
  431.         return true;
  432. }
  433.  
  434. bool CGeomCacheRenderNode::Initialize()
  435. {
  436.         assert(!m_bInitialized);
  437.         if (m_bInitialized)
  438.         {
  439.                 return true;
  440.         }
  441.  
  442.         if (m_pGeomCache)
  443.         {
  444.                 if (!InitializeRenderMeshes())
  445.                 {
  446.                         return false;
  447.                 }
  448.  
  449.                 const std::vector<SGeomCacheStaticMeshData>& staticMeshData = m_pGeomCache->GetStaticMeshData();
  450.  
  451.                 const uint numMeshes = staticMeshData.size();
  452.                 for (uint i = 0; i < numMeshes; ++i)
  453.                 {
  454.                         const SGeomCacheStaticMeshData& meshData = staticMeshData[i];
  455.                         uint numMaterials = meshData.m_materialIds.size();
  456.  
  457.                         for (uint j = 0; j < numMaterials; ++j)
  458.                         {
  459.                                 const uint16 materialId = meshData.m_materialIds[j];
  460.                                 if (m_pRenderElements.find(materialId) == m_pRenderElements.end())
  461.                                 {
  462.                                         CREGeomCache* pRenderElement = static_cast<CREGeomCache*>(GetRenderer()->EF_CreateRE(eDATA_GeomCache));
  463.  
  464.                                         SGeomCacheRenderElementData renderElementData;
  465.                                         renderElementData.m_pRenderElement = pRenderElement;
  466.                                         renderElementData.m_pUpdateState = (volatile int*)NULL;
  467.                                         renderElementData.m_pCurrentFillData = NULL;
  468.  
  469.                                         m_pRenderElements[materialId] = renderElementData;
  470.                                         pRenderElement->InitializeRenderElement(numMeshes, &m_renderMeshes[0], materialId);
  471.                                 }
  472.                         }
  473.                 }
  474.  
  475.                 GetGeomCacheManager()->RegisterForStreaming(this);
  476.  
  477.                 m_bInitialized = true;
  478.  
  479.                 return true;
  480.         }
  481.  
  482.         return false;
  483. }
  484.  
  485. void CGeomCacheRenderNode::Clear(bool bWaitForStreamingJobs)
  486. {
  487.         m_bInitialized = false;
  488.  
  489.         GetGeomCacheManager()->UnRegisterForStreaming(this, bWaitForStreamingJobs);
  490.  
  491.         m_renderMeshes.clear();
  492.         m_renderMeshUpdateContexts.clear();
  493.  
  494.         for (TRenderElementMap::iterator iter = m_pRenderElements.begin(); iter != m_pRenderElements.end(); ++iter)
  495.         {
  496.                 CREGeomCache* pCREGeomCache = iter->second.m_pRenderElement;
  497.                 pCREGeomCache->Release();
  498.         }
  499.  
  500.         m_currentAABB = AABB(0.0f);
  501.         m_currentDisplayAABB = AABB(0.0f);
  502.         m_pRenderElements.clear();
  503. }
  504.  
  505. void CGeomCacheRenderNode::SetPlaybackTime(const float time)
  506. {
  507.         if (m_pGeomCache)
  508.         {
  509.                 const float duration = m_pGeomCache->GetDuration();
  510.                 const bool bInsideTimeRange = (time >= 0.0f && (m_bLooping || time <= duration));
  511.  
  512.                 float clampedTime = time < 0.0f ? 0.0f : time;
  513.                 if (!m_bLooping)
  514.                 {
  515.                         clampedTime = time > duration ? duration : time;
  516.                 }
  517.  
  518.                 m_playbackTime = clampedTime;
  519.                 m_streamingTime = clampedTime;
  520.  
  521.                 if (m_pGeomCache && bInsideTimeRange)
  522.                 {
  523.                         StartStreaming(clampedTime);
  524.                         return;
  525.                 }
  526.         }
  527.  
  528.         StopStreaming();
  529. }
  530.  
  531. void CGeomCacheRenderNode::StartStreaming(const float time)
  532. {
  533.         if (m_pGeomCache && time >= 0.0f && (m_bLooping || time <= m_pGeomCache->GetDuration()))
  534.         {
  535.                 m_streamingTime = time;
  536.                 m_bIsStreaming = true;
  537.         }
  538. }
  539.  
  540. void CGeomCacheRenderNode::StopStreaming()
  541. {
  542.         m_bIsStreaming = false;
  543. }
  544.  
  545. bool CGeomCacheRenderNode::IsLooping() const
  546. {
  547.         return m_bLooping;
  548. }
  549.  
  550. void CGeomCacheRenderNode::SetLooping(const bool bEnable)
  551. {
  552.         m_bLooping = bEnable;
  553. }
  554.  
  555. bool CGeomCacheRenderNode::IsStreaming() const
  556. {
  557.         return m_bIsStreaming && m_pGeomCache && !m_pGeomCache->PlaybackFromMemory();
  558. }
  559.  
  560. float CGeomCacheRenderNode::GetPrecachedTime() const
  561. {
  562.         return GetGeomCacheManager()->GetPrecachedTime(this);
  563. }
  564.  
  565. void CGeomCacheRenderNode::StartAsyncUpdate()
  566. {
  567.         FUNCTION_PROFILER_3DENGINE;
  568.  
  569.         m_bTransformReady = false;
  570.  
  571.         for (TRenderElementMap::iterator iter = m_pRenderElements.begin(); iter != m_pRenderElements.end(); ++iter)
  572.         {
  573.                 SGeomCacheRenderElementData& data = iter->second;
  574.                 CREGeomCache* pCREGeomCache = data.m_pRenderElement;
  575.                 data.m_pUpdateState = pCREGeomCache->SetAsyncUpdateState(data.m_threadId);
  576.                 data.m_pCurrentFillData = pCREGeomCache->GetMeshFillDataPtr();
  577.         }
  578.  
  579.         const std::vector<SGeomCacheStaticMeshData>& staticMeshData = m_pGeomCache->GetStaticMeshData();
  580.  
  581.         const uint numDynamicRenderMeshes = m_renderMeshUpdateContexts.size();
  582.         for (uint i = 0; i < numDynamicRenderMeshes; ++i)
  583.         {
  584.                 SGeomCacheRenderMeshUpdateContext& updateContext = m_renderMeshUpdateContexts[i];
  585.  
  586.                 _smart_ptr<IRenderMesh> pRenderMesh = SetupDynamicRenderMesh(updateContext);
  587.                 m_renderMeshUpdateContexts[i].m_pRenderMesh = pRenderMesh;
  588.  
  589.                 const SGeomCacheStaticMeshData& currentMeshData = staticMeshData[updateContext.m_meshId];
  590.                 const uint numMaterials = currentMeshData.m_materialIds.size();
  591.                 for (uint j = 0; j < numMaterials; ++j)
  592.                 {
  593.                         const uint16 materialId = currentMeshData.m_materialIds[j];
  594.                         SGeomCacheRenderElementData& data = m_pRenderElements[materialId];
  595.                         CREGeomCache::SMeshRenderData& meshData = (*data.m_pCurrentFillData)[updateContext.m_meshId];
  596.                         meshData.m_pRenderMesh = pRenderMesh;
  597.                 }
  598.         }
  599. }
  600.  
  601. void CGeomCacheRenderNode::SkipFrameFill()
  602. {
  603.         const uint numDynamicRenderMeshes = m_renderMeshUpdateContexts.size();
  604.         for (uint i = 0; i < numDynamicRenderMeshes; ++i)
  605.         {
  606.                 SGeomCacheRenderMeshUpdateContext& updateContext = m_renderMeshUpdateContexts[i];
  607.                 if (updateContext.m_pUpdateState)
  608.                 {
  609.                         CryInterlockedDecrement(updateContext.m_pUpdateState);
  610.                 }
  611.         }
  612.  
  613.         for (TRenderElementMap::iterator iter = m_pRenderElements.begin(); iter != m_pRenderElements.end(); ++iter)
  614.         {
  615.                 CryInterlockedDecrement(iter->second.m_pUpdateState);
  616.         }
  617.  
  618.         m_bTransformReady = true;
  619.         m_bTransformReadyCV.Notify();
  620. }
  621.  
  622. bool CGeomCacheRenderNode::FillFrameAsync(const char* const pFloorFrameData, const char* const pCeilFrameData, const float lerpFactor)
  623. {
  624.         FUNCTION_PROFILER_3DENGINE;
  625.  
  626.         CryAutoLock<CryCriticalSection> fillLock(m_fillCS);
  627.  
  628.         if ((m_renderMeshes.empty() && m_renderMeshUpdateContexts.empty())
  629.             || (!m_renderMeshUpdateContexts.empty() && m_renderMeshUpdateContexts[0].m_pUpdateState == NULL)
  630.             || (m_standInVisible != eStandInType_None && m_bFilledFrameOnce))
  631.         {
  632.                 return false;
  633.         }
  634.  
  635.         const CGeomCache* const pGeomCache = m_pGeomCache;
  636.         assert(pGeomCache);
  637.  
  638.         if (!pGeomCache)
  639.         {
  640.                 return false;
  641.         }
  642.  
  643.         const std::vector<SGeomCacheStaticMeshData>& staticMeshData = pGeomCache->GetStaticMeshData();
  644.         const std::vector<SGeomCacheStaticNodeData>& staticNodeData = pGeomCache->GetStaticNodeData();
  645.  
  646.         const uint numMeshes = staticMeshData.size();
  647.         const uint numNodes = staticNodeData.size();
  648.  
  649.         if (numMeshes == 0 || numNodes == 0)
  650.         {
  651.                 return false;
  652.         }
  653.  
  654.         // Computer pointers to mesh & node data in frames
  655.         const GeomCacheFile::SFrameHeader* const floorFrameHeader = reinterpret_cast<const GeomCacheFile::SFrameHeader* const>(pFloorFrameData);
  656.         const char* pFloorMeshData = pFloorFrameData + sizeof(GeomCacheFile::SFrameHeader);
  657.         const char* const pFloorNodeData = pFloorFrameData + sizeof(GeomCacheFile::SFrameHeader) + floorFrameHeader->m_nodeDataOffset;
  658.  
  659.         const GeomCacheFile::SFrameHeader* const ceilFrameHeader = reinterpret_cast<const GeomCacheFile::SFrameHeader* const>(pCeilFrameData);
  660.         const char* pCeilMeshData = pCeilFrameData + sizeof(GeomCacheFile::SFrameHeader);
  661.         const char* const pCeilNodeData = pCeilFrameData + sizeof(GeomCacheFile::SFrameHeader) + ceilFrameHeader->m_nodeDataOffset;
  662.  
  663.         // Update geom cache AABB
  664.         AABB floorAABB(Vec3(floorFrameHeader->m_frameAABBMin[0], floorFrameHeader->m_frameAABBMin[1], floorFrameHeader->m_frameAABBMin[2]),
  665.                        Vec3(floorFrameHeader->m_frameAABBMax[0], floorFrameHeader->m_frameAABBMax[1], floorFrameHeader->m_frameAABBMax[2]));
  666.         AABB ceilAABB(Vec3(ceilFrameHeader->m_frameAABBMin[0], ceilFrameHeader->m_frameAABBMin[1], ceilFrameHeader->m_frameAABBMin[2]),
  667.                       Vec3(ceilFrameHeader->m_frameAABBMax[0], ceilFrameHeader->m_frameAABBMax[1], ceilFrameHeader->m_frameAABBMax[2]));
  668.  
  669.         m_currentDisplayAABB = floorAABB;
  670.         m_currentDisplayAABB.Add(ceilAABB);
  671.  
  672.         // Update meshes & clear instances
  673.         for (uint meshId = 0; meshId < numMeshes; ++meshId)
  674.         {
  675.                 const SGeomCacheStaticMeshData& meshData = staticMeshData[meshId];
  676.                 for (TRenderElementMap::iterator iter = m_pRenderElements.begin(); iter != m_pRenderElements.end(); ++iter)
  677.                 {
  678.                         SGeomCacheRenderElementData& data = iter->second;
  679.                         (*data.m_pCurrentFillData)[meshId].m_instances.clear();
  680.                 }
  681.         }
  682.  
  683.         // Add instance for current frame
  684.         uint currentMeshIndex = 0;
  685.         uint currentNodeIndex = 0;
  686.         uint currentNodeDataOffset = 0;
  687.  
  688.         UpdateTransformsRec(currentMeshIndex, currentNodeIndex, staticNodeData, staticMeshData,
  689.                             currentNodeDataOffset, pFloorNodeData, pCeilNodeData, QuatTNS(IDENTITY), lerpFactor);
  690.  
  691.         m_bTransformReady = true;
  692.         m_bTransformReadyCV.Notify();
  693.  
  694.         UpdatePhysicalEntity(NULL);
  695.  
  696.         uint currentRenderMesh = 0;
  697.         for (uint meshId = 0; meshId < numMeshes; ++meshId)
  698.         {
  699.                 const SGeomCacheStaticMeshData* pStaticMeshData = &staticMeshData[meshId];
  700.                 if (pStaticMeshData->m_animatedStreams != 0)
  701.                 {
  702.                         size_t offsetToNextMesh = 0;
  703.                         float meshLerpFactor = lerpFactor;
  704.                         SGeomCacheRenderMeshUpdateContext* pUpdateContext = &m_renderMeshUpdateContexts[currentRenderMesh++];
  705.  
  706.                         if (GeomCacheDecoder::PrepareFillMeshData(*pUpdateContext, *pStaticMeshData, pFloorMeshData, pCeilMeshData, offsetToNextMesh, meshLerpFactor))
  707.                         {
  708.                                 TGeomCacheUpdateMeshJob meshUpdateJob(pUpdateContext, pStaticMeshData, pFloorMeshData, pCeilMeshData, meshLerpFactor);
  709.                                 meshUpdateJob.SetClassInstance(this);
  710.                                 meshUpdateJob.SetPriorityLevel(JobManager::eRegularPriority);
  711.                                 meshUpdateJob.Run();
  712.                         }
  713.                         else
  714.                         {
  715.                                 CryInterlockedDecrement(pUpdateContext->m_pUpdateState);
  716.                         }
  717.  
  718.                         pFloorMeshData += offsetToNextMesh;
  719.                         pCeilMeshData += offsetToNextMesh;
  720.                 }
  721.         }
  722.  
  723.         for (TRenderElementMap::iterator iter = m_pRenderElements.begin(); iter != m_pRenderElements.end(); ++iter)
  724.         {
  725.                 SGeomCacheRenderElementData& data = iter->second;
  726.                 data.m_pRenderElement->DisplayFilledBuffer(data.m_threadId);
  727.                 CryInterlockedDecrement(iter->second.m_pUpdateState);
  728.         }
  729.  
  730.         m_bFilledFrameOnce = true;
  731.         return true;
  732. }
  733.  
  734. void CGeomCacheRenderNode::UpdateMesh_JobEntry(SGeomCacheRenderMeshUpdateContext* pUpdateContext, SGeomCacheStaticMeshData* pStaticMeshData,
  735.                                                const char* pFloorMeshData, const char* pCeilMeshData, float lerpFactor)
  736. {
  737.         GeomCacheDecoder::FillMeshDataFromDecodedFrame(m_bFilledFrameOnce, *pUpdateContext, *pStaticMeshData, pFloorMeshData, pCeilMeshData, lerpFactor);
  738.         CryInterlockedDecrement(pUpdateContext->m_pUpdateState);
  739. }
  740.  
  741. void CGeomCacheRenderNode::ClearFillData()
  742. {
  743.         FUNCTION_PROFILER_3DENGINE;
  744.  
  745.         const std::vector<SGeomCacheStaticMeshData>& staticMeshData = m_pGeomCache->GetStaticMeshData();
  746.         const uint numMeshes = staticMeshData.size();
  747.  
  748.         // Clear dynamic render meshes in fill buffer to release their unused memory
  749.         for (uint meshId = 0; meshId < numMeshes; ++meshId)
  750.         {
  751.                 const SGeomCacheStaticMeshData& meshData = staticMeshData[meshId];
  752.  
  753.                 if (meshData.m_animatedStreams != 0)
  754.                 {
  755.                         for (TRenderElementMap::iterator iter = m_pRenderElements.begin(); iter != m_pRenderElements.end(); ++iter)
  756.                         {
  757.                                 SGeomCacheRenderElementData& data = iter->second;
  758.                                 DynArray<CREGeomCache::SMeshRenderData>* pFillData = data.m_pRenderElement->GetMeshFillDataPtr();
  759.                                 (*pFillData)[meshId].m_pRenderMesh = NULL;
  760.                         }
  761.                 }
  762.         }
  763. }
  764.  
  765. void CGeomCacheRenderNode::InitTransformsRec(uint& currentNodeIndex, const std::vector<SGeomCacheStaticNodeData>& staticNodeData, const QuatTNS& currentTransform)
  766. {
  767.         const SGeomCacheStaticNodeData& currentNodeData = staticNodeData[currentNodeIndex];
  768.         const QuatTNS newTransformQuat = currentTransform * currentNodeData.m_localTransform;
  769.         const Matrix34 newTransformMatrix(newTransformQuat);
  770.         m_nodeMatrices[currentNodeIndex] = newTransformMatrix;
  771.  
  772.         currentNodeIndex += 1;
  773.  
  774.         const uint32 numChildren = currentNodeData.m_numChildren;
  775.         for (uint32 i = 0; i < numChildren; ++i)
  776.         {
  777.                 InitTransformsRec(currentNodeIndex, staticNodeData, newTransformQuat);
  778.         }
  779. }
  780.  
  781. void CGeomCacheRenderNode::UpdateTransformsRec(uint& currentNodeIndex, uint& currentMeshIndex, const std::vector<SGeomCacheStaticNodeData>& staticNodeData,
  782.                                                const std::vector<SGeomCacheStaticMeshData>& staticMeshData, uint& currentNodeDataOffset, const char* const pFloorNodeData,
  783.                                                const char* const pCeilNodeData, const QuatTNS& currentTransform, const float lerpFactor)
  784. {
  785.         const SGeomCacheStaticNodeData& currentNodeData = staticNodeData[currentNodeIndex];
  786.  
  787.         const uint32 floorNodeFlags = *reinterpret_cast<const uint32* const>(pFloorNodeData + currentNodeDataOffset);
  788.         const uint32 ceilNodeFlags = *reinterpret_cast<const uint32* const>(pCeilNodeData + currentNodeDataOffset);
  789.         currentNodeDataOffset += sizeof(uint32);
  790.  
  791.         QuatTNS newTransformQuat;
  792.  
  793.         // Update transform
  794.         if (currentNodeData.m_transformType == GeomCacheFile::eTransformType_Constant)
  795.         {
  796.                 // Matrix from static data
  797.                 newTransformQuat = currentTransform * currentNodeData.m_localTransform;
  798.         }
  799.         else
  800.         {
  801.                 // Matrix from frame data
  802.                 const QuatTNS* const pFloorTransform = reinterpret_cast<const QuatTNS* const>(pFloorNodeData + currentNodeDataOffset);
  803.                 const QuatTNS* const pCeilTransform = reinterpret_cast<const QuatTNS* const>(pCeilNodeData + currentNodeDataOffset);
  804.  
  805.                 QuatTNS interpolatedTransform;
  806.                 if (!(floorNodeFlags& GeomCacheFile::eFrameFlags_Hidden) && !(ceilNodeFlags & GeomCacheFile::eFrameFlags_Hidden))
  807.                 {
  808.                         interpolatedTransform.q = Quat::CreateSlerp(pFloorTransform->q, pCeilTransform->q, lerpFactor);
  809.                         interpolatedTransform.t = Vec3::CreateLerp(pFloorTransform->t, pCeilTransform->t, lerpFactor);
  810.                         interpolatedTransform.s = Diag33::CreateLerp(pFloorTransform->s, pCeilTransform->s, lerpFactor);
  811.                 }
  812.                 else if (!(floorNodeFlags & GeomCacheFile::eFrameFlags_Hidden))
  813.                 {
  814.                         interpolatedTransform = *pFloorTransform;
  815.                 }
  816.                 else if (!(ceilNodeFlags & GeomCacheFile::eFrameFlags_Hidden))
  817.                 {
  818.                         interpolatedTransform = *pCeilTransform;
  819.                 }
  820.                 else
  821.                 {
  822.                         interpolatedTransform.SetIdentity();
  823.                 }
  824.  
  825.                 newTransformQuat = currentTransform * interpolatedTransform;
  826.                 currentNodeDataOffset += sizeof(QuatTNS);
  827.         }
  828.  
  829.         Matrix34 newTransformMatrix(newTransformQuat);
  830.  
  831.         if (currentNodeData.m_type == GeomCacheFile::eNodeType_Mesh)
  832.         {
  833.                 const SGeomCacheStaticMeshData& currentMeshData = staticMeshData[currentNodeData.m_meshOrGeometryIndex];
  834.  
  835.                 const bool bVisible = ((floorNodeFlags& GeomCacheFile::eFrameFlags_Hidden) == 0);
  836.  
  837.                 if (bVisible)
  838.                 {
  839.                         CREGeomCache::SMeshInstance meshInstance;
  840.                         meshInstance.m_aabb = currentMeshData.m_aabb;
  841.                         meshInstance.m_matrix = newTransformMatrix;
  842.                         meshInstance.m_prevMatrix = m_bFilledFrameOnce ? m_nodeMatrices[currentNodeIndex] : newTransformMatrix;
  843.  
  844.         #ifndef _RELEASE
  845.                         const int debugDrawMode = GetCVars()->e_GeomCacheDebugDrawMode;
  846.                         if (debugDrawMode == 0 || debugDrawMode > 2
  847.                             || (debugDrawMode == 1 && currentMeshData.m_animatedStreams != 0)
  848.                             || (debugDrawMode == 2 && currentMeshData.m_animatedStreams == 0))
  849.         #endif
  850.                         {
  851.                                 const uint numMaterials = currentMeshData.m_materialIds.size();
  852.                                 for (uint i = 0; i < numMaterials; ++i)
  853.                                 {
  854.                                         const uint16 materialId = currentMeshData.m_materialIds[i];
  855.                                         SGeomCacheRenderElementData& data = m_pRenderElements[materialId];
  856.                                         (*data.m_pCurrentFillData)[currentNodeData.m_meshOrGeometryIndex].m_instances.push_back(meshInstance);
  857.                                 }
  858.                         }
  859.                 }
  860.         }
  861.  
  862.         m_nodeMatrices[currentNodeIndex] = newTransformMatrix;
  863.  
  864.         currentNodeIndex += 1;
  865.  
  866.         const uint32 numChildren = currentNodeData.m_numChildren;
  867.         for (uint32 i = 0; i < numChildren; ++i)
  868.         {
  869.                 UpdateTransformsRec(currentNodeIndex, currentMeshIndex, staticNodeData, staticMeshData, currentNodeDataOffset,
  870.                                     pFloorNodeData, pCeilNodeData, newTransformQuat, lerpFactor);
  871.         }
  872. }
  873.  
  874. void CGeomCacheRenderNode::FillRenderObject(const SRendParams& rendParams, const SRenderingPassInfo& passInfo, IMaterial* pMaterial, CRenderObject* pRenderObject)
  875. {
  876.         FUNCTION_PROFILER_3DENGINE;
  877.  
  878.         IRenderNode* const pRenderNode = rendParams.pRenderNode;
  879.         IRenderer* const pRenderer = GetRenderer();
  880.  
  881.         pRenderObject->m_pRenderNode = rendParams.pRenderNode;
  882.         pRenderObject->m_fDistance = rendParams.fDistance;
  883.  
  884.         pRenderObject->m_ObjFlags |= FOB_TRANS_MASK | FOB_DYNAMIC_OBJECT;
  885.         pRenderObject->m_ObjFlags |= rendParams.dwFObjFlags;
  886.  
  887.         pRenderObject->m_II.m_AmbColor = rendParams.AmbientColor;
  888.  
  889.         if (rendParams.nTextureID >= 0)
  890.         {
  891.                 pRenderObject->m_nTextureID = rendParams.nTextureID;
  892.         }
  893.  
  894.         pRenderObject->m_II.m_Matrix = *rendParams.pMatrix;
  895.         pRenderObject->m_nClipVolumeStencilRef = rendParams.nClipVolumeStencilRef;
  896.  
  897.         SRenderObjData* pRenderObjData = pRenderObject->GetObjData();
  898.         if (pRenderObjData)
  899.         {
  900.                 pRenderObjData->m_uniqueObjectId = reinterpret_cast<uintptr_t>(this);
  901.                 pRenderObjData->m_pLayerEffectParams = rendParams.pLayerEffectParams;
  902.                 pRenderObjData->m_nVisionParams = rendParams.nVisionParams;
  903.                 pRenderObjData->m_nHUDSilhouetteParams = rendParams.nHUDSilhouettesParams;
  904.         }
  905.  
  906.         pRenderObject->m_ObjFlags |= FOB_INSHADOW;
  907.         pRenderObject->m_fAlpha = rendParams.fAlpha;
  908.         pRenderObject->m_DissolveRef = rendParams.nDissolveRef;
  909.  
  910.         if (rendParams.nAfterWater)
  911.         {
  912.                 pRenderObject->m_ObjFlags |= FOB_AFTER_WATER;
  913.         }
  914.         else
  915.         {
  916.                 pRenderObject->m_ObjFlags &= ~FOB_AFTER_WATER;
  917.         }
  918.  
  919.         pRenderObject->m_pCurrMaterial = pMaterial;
  920. }
  921.  
  922. bool CGeomCacheRenderNode::InitializeRenderMeshes()
  923. {
  924.         const std::vector<SGeomCacheStaticMeshData>& staticMeshData = m_pGeomCache->GetStaticMeshData();
  925.  
  926.         const uint numMeshes = staticMeshData.size();
  927.         for (uint i = 0; i < numMeshes; ++i)
  928.         {
  929.                 const SGeomCacheStaticMeshData& meshData = staticMeshData[i];
  930.  
  931.                 IRenderMesh* pRenderMesh = NULL;
  932.  
  933.                 // Only meshes with constant topology for now. TODO: Add support for heterogeneous meshes.
  934.                 if (meshData.m_animatedStreams == 0)
  935.                 {
  936.                         pRenderMesh = GetGeomCacheManager()->GetMeshManager().GetStaticRenderMesh(meshData.m_hash);
  937.  
  938.                         assert(pRenderMesh != NULL);
  939.                         if (!pRenderMesh)
  940.                         {
  941.                                 return false;
  942.                         }
  943.                 }
  944.                 else if (meshData.m_animatedStreams != 0)
  945.                 {
  946.                         SGeomCacheRenderMeshUpdateContext updateContext;
  947.                         updateContext.m_prevPositions.resize(meshData.m_numVertices, Vec3(0.0f, 0.0f, 0.0f));
  948.                         updateContext.m_meshId = i;
  949.                         m_renderMeshUpdateContexts.push_back(updateContext);
  950.                         pRenderMesh = NULL;
  951.                 }
  952.  
  953.                 m_renderMeshes.push_back(pRenderMesh);
  954.         }
  955.  
  956.         return true;
  957. }
  958.  
  959. _smart_ptr<IRenderMesh> CGeomCacheRenderNode::SetupDynamicRenderMesh(SGeomCacheRenderMeshUpdateContext& updateContext)
  960. {
  961.         FUNCTION_PROFILER_3DENGINE;
  962.  
  963.         const std::vector<SGeomCacheStaticMeshData>& staticMeshData = m_pGeomCache->GetStaticMeshData();
  964.         const SGeomCacheStaticMeshData& meshData = staticMeshData[updateContext.m_meshId];
  965.  
  966.         // Create zero cleared render mesh
  967.         const uint numMaterials = meshData.m_numIndices.size();
  968.         uint numIndices = 0;
  969.         for (uint i = 0; i < numMaterials; ++i)
  970.         {
  971.                 numIndices += meshData.m_numIndices[i];
  972.         }
  973.  
  974.         _smart_ptr<IRenderMesh> pRenderMesh = gEnv->pRenderer->CreateRenderMeshInitialized(NULL, meshData.m_numVertices,
  975.                                                                                            eVF_P3F_C4B_T2F, NULL, numIndices, prtTriangleList,
  976.                                                                                            "GeomCacheDynamicMesh", m_pGeomCache->GetFilePath(), eRMT_Dynamic);
  977.  
  978.         pRenderMesh->LockForThreadAccess();
  979.  
  980.         updateContext.m_pIndices = pRenderMesh->GetIndexPtr(FSL_VIDEO_CREATE);
  981.         updateContext.m_pPositions.data = (Vec3*)pRenderMesh->GetPosPtrNoCache(updateContext.m_pPositions.iStride, FSL_VIDEO_CREATE);
  982.         updateContext.m_pColors.data = (UCol*)pRenderMesh->GetColorPtr(updateContext.m_pColors.iStride, FSL_VIDEO_CREATE);
  983.         updateContext.m_pTexcoords.data = (Vec2*)pRenderMesh->GetUVPtrNoCache(updateContext.m_pTexcoords.iStride, FSL_VIDEO_CREATE);
  984.         updateContext.m_pTangents.data = (SPipTangents*)pRenderMesh->GetTangentPtr(updateContext.m_pTangents.iStride, FSL_VIDEO_CREATE);
  985.         updateContext.m_pVelocities.data = (Vec3*)pRenderMesh->GetVelocityPtr(updateContext.m_pVelocities.iStride, FSL_VIDEO_CREATE);
  986.  
  987.         CRenderChunk chunk;
  988.         chunk.nNumVerts = meshData.m_numVertices;
  989.         uint32 currentIndexOffset = 0;
  990.  
  991.         std::vector<CRenderChunk> chunks;
  992.         chunks.reserve(numMaterials);
  993.  
  994.         for (uint i = 0; i < numMaterials; ++i)
  995.         {
  996.                 chunk.nFirstIndexId = currentIndexOffset;
  997.                 chunk.nNumIndices = meshData.m_numIndices[i];
  998.                 chunk.m_nMatID = meshData.m_materialIds[i];
  999.                 chunks.push_back(chunk);
  1000.                 currentIndexOffset += chunk.nNumIndices;
  1001.         }
  1002.  
  1003.         pRenderMesh->SetRenderChunks(&chunks[0], numMaterials, false);
  1004.  
  1005.         updateContext.m_pUpdateState = pRenderMesh->SetAsyncUpdateState();
  1006.         pRenderMesh->UnLockForThreadAccess();
  1007.  
  1008.         return pRenderMesh;
  1009. }
  1010.  
  1011. void CGeomCacheRenderNode::SetStandIn(const char* pFilePath, const char* pMaterial)
  1012. {
  1013.         m_pStandIn = Get3DEngine()->LoadStatObj(pFilePath);
  1014.  
  1015.         if (m_pStandIn)
  1016.         {
  1017.                 m_pStandIn->SetMaterial(GetMatMan()->LoadMaterial(pMaterial));
  1018.         }
  1019. }
  1020.  
  1021. void CGeomCacheRenderNode::SetFirstFrameStandIn(const char* pFilePath, const char* pMaterial)
  1022. {
  1023.         m_pFirstFrameStandIn = Get3DEngine()->LoadStatObj(pFilePath);
  1024.  
  1025.         if (m_pFirstFrameStandIn)
  1026.         {
  1027.                 m_pFirstFrameStandIn->SetMaterial(GetMatMan()->LoadMaterial(pMaterial));
  1028.         }
  1029. }
  1030.  
  1031. void CGeomCacheRenderNode::SetLastFrameStandIn(const char* pFilePath, const char* pMaterial)
  1032. {
  1033.         m_pLastFrameStandIn = Get3DEngine()->LoadStatObj(pFilePath);
  1034.  
  1035.         if (m_pLastFrameStandIn)
  1036.         {
  1037.                 m_pLastFrameStandIn->SetMaterial(GetMatMan()->LoadMaterial(pMaterial));
  1038.         }
  1039. }
  1040.  
  1041. void CGeomCacheRenderNode::SetStandInDistance(const float distance)
  1042. {
  1043.         m_standInDistance = distance;
  1044. }
  1045.  
  1046. void CGeomCacheRenderNode::SetStreamInDistance(const float distance)
  1047. {
  1048.         m_streamInDistance = distance;
  1049. }
  1050.  
  1051. CGeomCacheRenderNode::EStandInType CGeomCacheRenderNode::SelectStandIn() const
  1052. {
  1053.         const bool bFirstFrame = m_playbackTime == 0.0f;
  1054.         const bool bLastFrame = !m_bLooping && (m_pGeomCache ? (m_playbackTime >= m_pGeomCache->GetDuration()) : false);
  1055.  
  1056.         if (bFirstFrame && m_pFirstFrameStandIn && m_pFirstFrameStandIn->GetRenderMesh())
  1057.         {
  1058.                 return eStandInType_FirstFrame;
  1059.         }
  1060.         else if (bLastFrame && m_pLastFrameStandIn && m_pLastFrameStandIn->GetRenderMesh())
  1061.         {
  1062.                 return eStandInType_LastFrame;
  1063.         }
  1064.         else if (m_pStandIn && m_pStandIn->GetRenderMesh())
  1065.         {
  1066.                 return eStandInType_Default;
  1067.         }
  1068.  
  1069.         return eStandInType_None;
  1070. }
  1071.  
  1072. IStatObj* CGeomCacheRenderNode::GetStandIn(const EStandInType type) const
  1073. {
  1074.         switch (type)
  1075.         {
  1076.         case eStandInType_Default:
  1077.                 return m_pStandIn;
  1078.         case eStandInType_FirstFrame:
  1079.                 return m_pFirstFrameStandIn;
  1080.         case eStandInType_LastFrame:
  1081.                 return m_pLastFrameStandIn;
  1082.         }
  1083.  
  1084.         return NULL;
  1085. }
  1086.  
  1087. void CGeomCacheRenderNode::DebugDraw(const SGeometryDebugDrawInfo& info, uint nodeIndex) const
  1088. {
  1089.         CryAutoLock<CryCriticalSection> fillLock(m_fillCS);
  1090.  
  1091.         if (!m_bDrawing)
  1092.         {
  1093.                 return;
  1094.         }
  1095.  
  1096.         switch (m_standInVisible)
  1097.         {
  1098.         case eStandInType_None:
  1099.                 {
  1100.                         if (m_pGeomCache && m_nodeMatrices.size() > 0)
  1101.                         {
  1102.                                 const std::vector<SGeomCacheStaticNodeData>& staticNodeData = m_pGeomCache->GetStaticNodeData();
  1103.                                 nodeIndex = std::min(nodeIndex, (uint)(staticNodeData.size() - 1));
  1104.                                 DebugDrawRec(info, nodeIndex, staticNodeData);
  1105.                         }
  1106.                         break;
  1107.                 }
  1108.         case eStandInType_Default:
  1109.                 {
  1110.                         m_pStandIn->DebugDraw(info);
  1111.                         break;
  1112.                 }
  1113.         case eStandInType_FirstFrame:
  1114.                 {
  1115.                         m_pFirstFrameStandIn->DebugDraw(info);
  1116.                         break;
  1117.                 }
  1118.         case eStandInType_LastFrame:
  1119.                 {
  1120.                         m_pLastFrameStandIn->DebugDraw(info);
  1121.                         break;
  1122.                 }
  1123.         }
  1124. }
  1125.  
  1126. void CGeomCacheRenderNode::DebugDrawRec(const SGeometryDebugDrawInfo& info,
  1127.                                         uint& currentNodeIndex, const std::vector<SGeomCacheStaticNodeData>& staticNodeData) const
  1128. {
  1129.         const SGeomCacheStaticNodeData& currentNodeData = staticNodeData[currentNodeIndex];
  1130.  
  1131.         if (currentNodeData.m_type == GeomCacheFile::eNodeType_Mesh)
  1132.         {
  1133.                 for (TRenderElementMap::const_iterator iter = m_pRenderElements.begin(); iter != m_pRenderElements.end(); ++iter)
  1134.                 {
  1135.                         CREGeomCache* pCREGeomCache = iter->second.m_pRenderElement;
  1136.                         DynArray<CREGeomCache::SMeshRenderData>* pFillData = pCREGeomCache->GetRenderDataPtr();
  1137.  
  1138.                         if (pFillData)
  1139.                         {
  1140.                                 CREGeomCache::SMeshRenderData& renderData = (*pFillData)[currentNodeData.m_meshOrGeometryIndex];
  1141.                                 IRenderMesh* pRenderMesh = renderData.m_pRenderMesh.get();
  1142.  
  1143.                                 if (renderData.m_instances.size() > 0 && pRenderMesh)
  1144.                                 {
  1145.                                         Matrix34 pieceMatrix = m_matrix * m_nodeMatrices[currentNodeIndex];
  1146.  
  1147.                                         SGeometryDebugDrawInfo subInfo = info;
  1148.                                         subInfo.tm = pieceMatrix;
  1149.  
  1150.                                         pRenderMesh->DebugDraw(subInfo, ~0);
  1151.                                         break;
  1152.                                 }
  1153.                         }
  1154.                 }
  1155.         }
  1156.  
  1157.         currentNodeIndex += 1;
  1158.  
  1159.         const uint32 numChildren = currentNodeData.m_numChildren;
  1160.         for (uint32 i = 0; i < numChildren; ++i)
  1161.         {
  1162.                 DebugDrawRec(info, currentNodeIndex, staticNodeData);
  1163.         }
  1164. }
  1165.  
  1166. bool CGeomCacheRenderNode::RayIntersectionRec(SRayHitInfo& hitInfo, IMaterial* pCustomMtl, uint* pHitNodeIndex,
  1167.                                               uint& currentNodeIndex, const std::vector<SGeomCacheStaticNodeData>& staticNodeData, SRayHitInfo& hitOut, float& fMinDistance) const
  1168. {
  1169.         const SGeomCacheStaticNodeData& currentNodeData = staticNodeData[currentNodeIndex];
  1170.  
  1171.         bool bHit = false;
  1172.  
  1173.         if (currentNodeData.m_type == GeomCacheFile::eNodeType_Mesh)
  1174.         {
  1175.                 for (TRenderElementMap::const_iterator iter = m_pRenderElements.begin(); iter != m_pRenderElements.end(); ++iter)
  1176.                 {
  1177.                         CREGeomCache* pCREGeomCache = iter->second.m_pRenderElement;
  1178.                         DynArray<CREGeomCache::SMeshRenderData>* pFillData = pCREGeomCache->GetRenderDataPtr();
  1179.  
  1180.                         if (pFillData)
  1181.                         {
  1182.                                 CREGeomCache::SMeshRenderData& renderData = (*pFillData)[currentNodeData.m_meshOrGeometryIndex];
  1183.                                 IRenderMesh* pRenderMesh = renderData.m_pRenderMesh.get();
  1184.  
  1185.                                 if (renderData.m_instances.size() > 0 && pRenderMesh)
  1186.                                 {
  1187.                                         Matrix34 pieceMatrix = m_matrix * m_nodeMatrices[currentNodeIndex];
  1188.  
  1189.                                         AABB meshAABB = m_pGeomCache->GetStaticMeshData()[currentNodeData.m_meshOrGeometryIndex].m_aabb;
  1190.  
  1191.                                         AABB pieceWorldAABB;
  1192.                                         pieceWorldAABB.SetTransformedAABB(pieceMatrix, meshAABB);
  1193.  
  1194.                                         Vec3 vOut;
  1195.                                         if (!Intersect::Ray_AABB(hitInfo.inRay, pieceWorldAABB, vOut))
  1196.                                         {
  1197.                                                 continue;
  1198.                                         }
  1199.  
  1200.                                         Matrix34 invPieceMatrix = pieceMatrix.GetInverted();
  1201.  
  1202.                                         // Transform ray into sub-object local space.
  1203.                                         SRayHitInfo subHitInfo = hitInfo;
  1204.                                         ZeroStruct(subHitInfo);
  1205.                                         subHitInfo.inReferencePoint = invPieceMatrix.TransformPoint(hitInfo.inReferencePoint);
  1206.                                         subHitInfo.inRay.origin = invPieceMatrix.TransformPoint(hitInfo.inRay.origin);
  1207.                                         subHitInfo.inRay.direction = invPieceMatrix.TransformVector(hitInfo.inRay.direction);
  1208.  
  1209.                                         if (CRenderMeshUtils::RayIntersection(pRenderMesh, subHitInfo, NULL))
  1210.                                         {
  1211.                                                 const uint materialId = iter->first;
  1212.                                                 IMaterial* pMaterial = const_cast<CGeomCacheRenderNode*>(this)->GetMaterial(NULL);
  1213.                                                 IMaterial* pSubMaterial = pMaterial->GetSafeSubMtl(materialId);
  1214.  
  1215.                                                 if (subHitInfo.nHitMatID == materialId)
  1216.                                                 {
  1217.                                                         subHitInfo.vHitPos = pieceMatrix.TransformPoint(subHitInfo.vHitPos);
  1218.                                                         subHitInfo.fDistance = hitInfo.inReferencePoint.GetDistance(subHitInfo.vHitPos);
  1219.  
  1220.                                                         if (subHitInfo.fDistance < fMinDistance)
  1221.                                                         {
  1222.                                                                 bHit = true;
  1223.                                                                 fMinDistance = subHitInfo.fDistance;
  1224.                                                                 hitOut = subHitInfo;
  1225.  
  1226.                                                                 hitOut.nHitMatID = materialId;
  1227.                                                                 if (pSubMaterial)
  1228.                                                                 {
  1229.                                                                         hitInfo.nHitSurfaceID = pSubMaterial->GetSurfaceTypeId();
  1230.                                                                 }
  1231.  
  1232.                                                                 if (pHitNodeIndex)
  1233.                                                                 {
  1234.                                                                         *pHitNodeIndex = currentNodeIndex;
  1235.                                                                 }
  1236.                                                         }
  1237.                                                 }
  1238.                                         }
  1239.                                 }
  1240.                         }
  1241.                 }
  1242.         }
  1243.  
  1244.         currentNodeIndex += 1;
  1245.  
  1246.         const uint32 numChildren = currentNodeData.m_numChildren;
  1247.         for (uint32 i = 0; i < numChildren; ++i)
  1248.         {
  1249.                 bHit = RayIntersectionRec(hitInfo, pCustomMtl, pHitNodeIndex, currentNodeIndex, staticNodeData, hitOut, fMinDistance) || bHit;
  1250.         }
  1251.  
  1252.         return bHit;
  1253. }
  1254.  
  1255.         #ifndef _RELEASE
  1256. void CGeomCacheRenderNode::DebugRender()
  1257. {
  1258.         if (m_pGeomCache && GetCVars()->e_GeomCacheDebugDrawMode == 3)
  1259.         {
  1260.                 const std::vector<SGeomCacheStaticNodeData>& staticNodeData = m_pGeomCache->GetStaticNodeData();
  1261.                 uint currentNodeIndex = 0;
  1262.                 InstancingDebugDrawRec(currentNodeIndex, staticNodeData);
  1263.         }
  1264. }
  1265.  
  1266. void CGeomCacheRenderNode::InstancingDebugDrawRec(uint& currentNodeIndex, const std::vector<SGeomCacheStaticNodeData>& staticNodeData)
  1267. {
  1268.         CryAutoLock<CryCriticalSection> fillLock(m_fillCS);
  1269.  
  1270.         const SGeomCacheStaticNodeData& currentNodeData = staticNodeData[currentNodeIndex];
  1271.  
  1272.         ColorF colors[] = {
  1273.                 Col_Aquamarine,      Col_Blue,              Col_BlueViolet,      Col_Brown,        Col_CadetBlue,      Col_Coral,           Col_CornflowerBlue,    Col_Cyan,
  1274.                 Col_DimGrey,         Col_FireBrick,         Col_ForestGreen,     Col_Gold,         Col_Goldenrod,      Col_Gray,            Col_Green,             Col_GreenYellow,Col_IndianRed,         Col_Khaki,
  1275.                 Col_LightBlue,       Col_LightGray,         Col_LightSteelBlue,  Col_LightWood,    Col_LimeGreen,      Col_Magenta,         Col_Maroon,            Col_MedianWood, Col_MediumAquamarine,
  1276.                 Col_MediumBlue,      Col_MediumForestGreen, Col_MediumGoldenrod, Col_MediumOrchid, Col_MediumSeaGreen, Col_MediumSlateBlue, Col_MediumSpringGreen,
  1277.                 Col_MediumTurquoise, Col_MediumVioletRed,   Col_MidnightBlue,    Col_Navy,         Col_NavyBlue,       Col_Orange,          Col_OrangeRed,         Col_Orchid,     Col_PaleGreen,
  1278.                 Col_Pink,            Col_Plum,              Col_Red,             Col_Salmon,       Col_SeaGreen,       Col_Sienna,          Col_SkyBlue,           Col_SlateBlue,  Col_SpringGreen,       Col_SteelBlue,Col_Tan,
  1279.                 Col_Thistle,         Col_Transparent,       Col_Turquoise,       Col_Violet,       Col_VioletRed,      Col_Wheat,           Col_Yellow
  1280.         };
  1281.  
  1282.         const uint kNumColors = sizeof(colors) / sizeof(ColorF);
  1283.  
  1284.         if (currentNodeData.m_type == GeomCacheFile::eNodeType_Mesh)
  1285.         {
  1286.                 for (TRenderElementMap::const_iterator iter = m_pRenderElements.begin(); iter != m_pRenderElements.end(); ++iter)
  1287.                 {
  1288.                         CREGeomCache* pCREGeomCache = iter->second.m_pRenderElement;
  1289.                         DynArray<CREGeomCache::SMeshRenderData>* pFillData = pCREGeomCache->GetRenderDataPtr();
  1290.  
  1291.                         if (pFillData)
  1292.                         {
  1293.                                 CREGeomCache::SMeshRenderData& renderData = (*pFillData)[currentNodeData.m_meshOrGeometryIndex];
  1294.                                 IRenderMesh* pRenderMesh = renderData.m_pRenderMesh.get();
  1295.  
  1296.                                 if (renderData.m_instances.size() > 0 && pRenderMesh)
  1297.                                 {
  1298.                                         Matrix34 pieceMatrix = m_matrix * m_nodeMatrices[currentNodeIndex];
  1299.  
  1300.                                         SGeometryDebugDrawInfo info;
  1301.                                         info.bNoLines = true;
  1302.                                         info.bDrawInFront = false;
  1303.                                         info.tm = pieceMatrix;
  1304.  
  1305.                                         const uint64 kMul = 0x9ddfea08eb382d69ULL;
  1306.                                         uint64 hash = (uint64)alias_cast<UINT_PTR>(pRenderMesh);
  1307.                                         hash ^= (hash >> 47);
  1308.                                         hash *= kMul;
  1309.  
  1310.                                         info.color = colors[hash % kNumColors];
  1311.  
  1312.                                         pRenderMesh->DebugDraw(info);
  1313.                                         break;
  1314.                                 }
  1315.                         }
  1316.                 }
  1317.         }
  1318.  
  1319.         currentNodeIndex += 1;
  1320.  
  1321.         const uint32 numChildren = currentNodeData.m_numChildren;
  1322.         for (uint32 i = 0; i < numChildren; ++i)
  1323.         {
  1324.                 InstancingDebugDrawRec(currentNodeIndex, staticNodeData);
  1325.         }
  1326. }
  1327.         #endif
  1328.  
  1329. bool CGeomCacheRenderNode::RayIntersection(SRayHitInfo& hitInfo, IMaterial* pCustomMtl, uint* pNodeIndex) const
  1330. {
  1331.         CryAutoLock<CryCriticalSection> fillLock(m_fillCS);
  1332.  
  1333.         switch (m_standInVisible)
  1334.         {
  1335.         case eStandInType_None:
  1336.                 {
  1337.                         if (m_pGeomCache && m_nodeMatrices.size() > 0)
  1338.                         {
  1339.                                 const std::vector<SGeomCacheStaticNodeData>& staticNodeData = m_pGeomCache->GetStaticNodeData();
  1340.  
  1341.                                 SRayHitInfo hitOut;
  1342.                                 float fMinDistance = std::numeric_limits<float>::max();
  1343.                                 uint currentNodeIndex = 0;
  1344.  
  1345.                                 if (RayIntersectionRec(hitInfo, pCustomMtl, pNodeIndex, currentNodeIndex, staticNodeData, hitOut, fMinDistance))
  1346.                                 {
  1347.                                         // Restore input ray/reference point.
  1348.                                         hitOut.inReferencePoint = hitInfo.inReferencePoint;
  1349.                                         hitOut.inRay = hitInfo.inRay;
  1350.                                         hitOut.fDistance = fMinDistance;
  1351.  
  1352.                                         hitInfo = hitOut;
  1353.                                         return true;
  1354.                                 }
  1355.                         }
  1356.                         break;
  1357.                 }
  1358.         case eStandInType_Default:
  1359.                 {
  1360.                         return m_pStandIn->RayIntersection(hitInfo, pCustomMtl);
  1361.                 }
  1362.         case eStandInType_FirstFrame:
  1363.                 {
  1364.                         return m_pFirstFrameStandIn->RayIntersection(hitInfo, pCustomMtl);
  1365.                 }
  1366.         case eStandInType_LastFrame:
  1367.                 {
  1368.                         return m_pLastFrameStandIn->RayIntersection(hitInfo, pCustomMtl);
  1369.                 }
  1370.         }
  1371.  
  1372.         return false;
  1373. }
  1374.  
  1375. uint CGeomCacheRenderNode::GetNodeCount() const
  1376. {
  1377.         if (!m_pGeomCache)
  1378.         {
  1379.                 return 0;
  1380.         }
  1381.  
  1382.         const uint numNodes = m_pGeomCache->GetStaticNodeData().size();
  1383.         return numNodes;
  1384. }
  1385.  
  1386. Matrix34 CGeomCacheRenderNode::GetNodeTransform(const uint nodeIndex) const
  1387. {
  1388.         FUNCTION_PROFILER_3DENGINE;
  1389.  
  1390.         {
  1391.                 CryAutoLock<CryMutex> lock(m_bTransformsReadyCS);
  1392.                 while (!m_bTransformReady)
  1393.                 {
  1394.                         m_bTransformReadyCV.Wait(m_bTransformsReadyCS);
  1395.                 }
  1396.         }
  1397.  
  1398.         if (nodeIndex >= m_nodeMatrices.size() || !m_pGeomCache)
  1399.         {
  1400.                 return Matrix34(IDENTITY);
  1401.         }
  1402.  
  1403.         return m_nodeMatrices[nodeIndex];
  1404. }
  1405.  
  1406. const char* CGeomCacheRenderNode::GetNodeName(const uint nodeIndex) const
  1407. {
  1408.         if (!m_pGeomCache)
  1409.         {
  1410.                 return "";
  1411.         }
  1412.  
  1413.         const std::vector<SGeomCacheStaticNodeData>& staticNodeData = m_pGeomCache->GetStaticNodeData();
  1414.         return staticNodeData[nodeIndex].m_name.c_str();
  1415. }
  1416.  
  1417. uint32 CGeomCacheRenderNode::GetNodeNameHash(const uint nodeIndex) const
  1418. {
  1419.         if (!m_pGeomCache)
  1420.         {
  1421.                 return 0;
  1422.         }
  1423.  
  1424.         const std::vector<SGeomCacheStaticNodeData>& staticNodeData = m_pGeomCache->GetStaticNodeData();
  1425.         return staticNodeData[nodeIndex].m_nameHash;
  1426. }
  1427.  
  1428. bool CGeomCacheRenderNode::IsNodeDataValid(const uint nodeIndex) const
  1429. {
  1430.         FUNCTION_PROFILER_3DENGINE;
  1431.  
  1432.         {
  1433.                 CryAutoLock<CryMutex> lock(m_bTransformsReadyCS);
  1434.                 while (!m_bTransformReady)
  1435.                 {
  1436.                         m_bTransformReadyCV.Wait(m_bTransformsReadyCS);
  1437.                 }
  1438.         }
  1439.  
  1440.         if (nodeIndex >= m_nodeMatrices.size() || !m_pGeomCache)
  1441.         {
  1442.                 return false;
  1443.         }
  1444.  
  1445.         return true;
  1446. }
  1447.  
  1448. void CGeomCacheRenderNode::InitPhysicalEntity(IPhysicalEntity* pPhysicalEntity, const pe_articgeomparams& params)
  1449. {
  1450.         m_pPhysicalEntity = pPhysicalEntity;
  1451.         UpdatePhysicalEntity(&params);
  1452. }
  1453.  
  1454. void CGeomCacheRenderNode::UpdatePhysicalEntity(const pe_articgeomparams* pParams)
  1455. {
  1456.         if (!m_pPhysicalEntity)
  1457.         {
  1458.                 return;
  1459.         }
  1460.  
  1461.         const std::vector<SGeomCacheStaticNodeData>& staticNodeData = m_pGeomCache->GetStaticNodeData();
  1462.         const std::vector<phys_geometry*>& physicsGeometries = m_pGeomCache->GetPhysicsGeometries();
  1463.  
  1464.         Matrix34 scaleMatrix = GetMatrix();
  1465.         const Vec3 scale = Vec3(scaleMatrix.GetColumn0().GetLength(), scaleMatrix.GetColumn1().GetLength(), scaleMatrix.GetColumn2().GetLength());
  1466.         scaleMatrix.SetScale(scale);
  1467.  
  1468.         const uint numNodes = staticNodeData.size();
  1469.         for (uint i = 0; i < numNodes; ++i)
  1470.         {
  1471.                 const SGeomCacheStaticNodeData& nodeData = staticNodeData[i];
  1472.                 if (nodeData.m_type == GeomCacheFile::eNodeType_PhysicsGeometry)
  1473.                 {
  1474.                         const Matrix34 nodeTransform = GetNodeTransform(i);
  1475.                         phys_geometry* pGeometry = physicsGeometries[nodeData.m_meshOrGeometryIndex];
  1476.                         if (pGeometry)
  1477.                         {
  1478.                                 Matrix34 nodeMatrix = scaleMatrix * nodeTransform;
  1479.  
  1480.                                 if (pParams)
  1481.                                 {
  1482.                                         pe_articgeomparams params = *pParams;
  1483.                                         m_pPhysicalEntity->AddGeometry(pGeometry, &params, i);
  1484.                                 }
  1485.  
  1486.                                 pe_params_part params;
  1487.                                 params.pMtx3x4 = &nodeMatrix;
  1488.                                 params.partid = i;
  1489.                                 m_pPhysicalEntity->SetParams(&params);
  1490.                         }
  1491.                 }
  1492.         }
  1493. }
  1494.  
  1495. void CGeomCacheRenderNode::UpdatePhysicalMaterials()
  1496. {
  1497.         if (m_pPhysicalEntity && m_pMaterial)
  1498.         {
  1499.                 int surfaceTypesId[MAX_SUB_MATERIALS] = { 0 };
  1500.                 const int numIds = m_pMaterial->FillSurfaceTypeIds(surfaceTypesId);
  1501.  
  1502.                 pe_params_part params;
  1503.                 params.nMats = numIds;
  1504.                 params.pMatMapping = surfaceTypesId;
  1505.                 m_pPhysicalEntity->SetParams(&params);
  1506.         }
  1507. }
  1508.  
  1509. void CGeomCacheRenderNode::UpdateStreamableComponents(float fImportance, float fDistance, bool bFullUpdate, int nLod, const float fInvScale, bool bDrawNear)
  1510. {
  1511.         CObjManager* pObjManager = GetObjManager();
  1512.         Matrix34A matrix = GetMatrix();
  1513.  
  1514.         const bool bAllowStandIn = GetCVars()->e_Lods != 0;
  1515.         const bool bStreamInGeomCache = !m_pStandIn || (fDistance <= std::max(m_standInDistance, m_streamInDistance)) || !bAllowStandIn;
  1516.         if (m_pGeomCache && bStreamInGeomCache)
  1517.         {
  1518.                 m_pGeomCache->UpdateStreamableComponents(fImportance, matrix, this, bFullUpdate);
  1519.         }
  1520.  
  1521.         static_cast<CMatInfo*>(m_pMaterial.get())->PrecacheMaterial(fDistance * fInvScale, NULL, bFullUpdate, bDrawNear);
  1522.  
  1523.         PrecacheStandIn(m_pStandIn, fImportance, fDistance, bFullUpdate, nLod, fInvScale, bDrawNear);
  1524.         PrecacheStandIn(m_pFirstFrameStandIn, fImportance, fDistance, bFullUpdate, nLod, fInvScale, bDrawNear);
  1525.         PrecacheStandIn(m_pLastFrameStandIn, fImportance, fDistance, bFullUpdate, nLod, fInvScale, bDrawNear);
  1526. }
  1527.  
  1528. void CGeomCacheRenderNode::PrecacheStandIn(IStatObj* pStandIn, float fImportance, float fDistance, bool bFullUpdate, int nLod, const float fInvScale, bool bDrawNear)
  1529. {
  1530.         if (pStandIn)
  1531.         {
  1532.                 IStatObj* pLod = pStandIn->GetLodObject(nLod, true);
  1533.                 if (pLod)
  1534.                 {
  1535.                         CObjManager* pObjManager = GetObjManager();
  1536.                         Matrix34A matrix = GetMatrix();
  1537.                         static_cast<CStatObj*>(pLod)->UpdateStreamableComponents(fImportance, matrix, bFullUpdate, nLod);
  1538.                         pObjManager->PrecacheStatObjMaterial(pLod->GetMaterial(), fDistance * fInvScale, pLod, bFullUpdate, bDrawNear);
  1539.                 }
  1540.         }
  1541. }
  1542.  
  1543. void CGeomCacheRenderNode::OnGeomCacheStaticDataLoaded()
  1544. {
  1545.         Initialize();
  1546. }
  1547.  
  1548. void CGeomCacheRenderNode::OnGeomCacheStaticDataUnloaded()
  1549. {
  1550.         Clear(false);
  1551. }
  1552.  
  1553. #endif
  1554.  
downloadGeomCacheRenderNode.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