BVB Source Codes

CRYENGINE Show GameVolume_Water.cpp Source code

Return Download CRYENGINE: download GameVolume_Water.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "GameVolume_Water.h"
  5.  
  6. #include <CryGame/IGameVolumes.h>
  7.  
  8. //#pragma optimize("", off)
  9. //#pragma inline_depth(0)
  10.  
  11. namespace
  12. {
  13. bool GetVolumeInfoForEntity(EntityId entityId, IGameVolumes::VolumeInfo& volumeInfo)
  14. {
  15.         IGameVolumes* pGameVolumesMgr = gEnv->pGameFramework->GetIGameVolumesManager();
  16.         if (pGameVolumesMgr != NULL)
  17.         {
  18.                 return pGameVolumesMgr->GetVolumeInfoForEntity(entityId, &volumeInfo);
  19.         }
  20.  
  21.         return false;
  22. }
  23. }
  24.  
  25. namespace GVW
  26. {
  27. void RegisterEvents(IGameObjectExtension& goExt, IGameObject& gameObject)
  28. {
  29.         const int eventID = eGFE_ScriptEvent;
  30.         gameObject.UnRegisterExtForEvents(&goExt, NULL, 0);
  31.         gameObject.RegisterExtForEvents(&goExt, &eventID, 1);
  32. }
  33. }
  34.  
  35. CGameVolume_Water::CGameVolume_Water()
  36.         : m_lastAwakeCheckPosition(ZERO)
  37.         , m_volumeDepth(0.0f)
  38.         , m_streamSpeed(0.0f)
  39.         , m_awakeAreaWhenMoving(false)
  40.         , m_isRiver(false)
  41. {
  42.         m_baseMatrix.SetIdentity();
  43.         m_initialMatrix.SetIdentity();
  44.  
  45.         m_segments.resize(1);
  46. }
  47.  
  48. CGameVolume_Water::~CGameVolume_Water()
  49. {
  50.         DestroyPhysicsAreas();
  51.  
  52.         if (gEnv->p3DEngine)
  53.         {
  54.                 WaterSegments::iterator iter = m_segments.begin();
  55.                 WaterSegments::iterator end = m_segments.end();
  56.                 while (iter != end)
  57.                 {
  58.                         if (iter->m_pWaterRenderNode)
  59.                         {
  60.                                 iter->m_pWaterRenderNode->ReleaseNode();
  61.                                 iter->m_pWaterRenderNode = NULL;
  62.                         }
  63.  
  64.                         ++iter;
  65.                 }
  66.         }
  67. }
  68.  
  69. bool CGameVolume_Water::Init(IGameObject* pGameObject)
  70. {
  71.         SetGameObject(pGameObject);
  72.  
  73.         if (!GetGameObject()->BindToNetwork())
  74.                 return false;
  75.  
  76.         return true;
  77. }
  78.  
  79. void CGameVolume_Water::PostInit(IGameObject* pGameObject)
  80. {
  81.         GVW::RegisterEvents(*this, *pGameObject);
  82.         SetupVolume();
  83.  
  84.         //////////////////////////////////////////////////////////////////////////
  85.         /// For debugging purposes
  86.         if (gEnv->IsEditor())
  87.         {
  88.                 GetGameObject()->EnableUpdateSlot(this, 0);
  89.         }
  90. }
  91.  
  92. bool CGameVolume_Water::ReloadExtension(IGameObject* pGameObject, const SEntitySpawnParams& params)
  93. {
  94.         ResetGameObject();
  95.  
  96.         GVW::RegisterEvents(*this, *pGameObject);
  97.  
  98.         CRY_ASSERT_MESSAGE(false, "CGameVolume_Water::ReloadExtension not implemented");
  99.  
  100.         return false;
  101. }
  102.  
  103. void CGameVolume_Water::Release()
  104. {
  105.         delete this;
  106. }
  107.  
  108. void CGameVolume_Water::Update(SEntityUpdateContext& ctx, int slot)
  109. {
  110.         if (gEnv->IsEditing())
  111.         {
  112.                 DebugDrawVolume();
  113.         }
  114. }
  115.  
  116. void CGameVolume_Water::HandleEvent(const SGameObjectEvent& gameObjectEvent)
  117. {
  118.         if ((gameObjectEvent.event == eGFE_ScriptEvent) && (gameObjectEvent.param != NULL))
  119.         {
  120.                 const char* eventName = static_cast<const char*>(gameObjectEvent.param);
  121.                 if (strcmp(eventName, "PhysicsEnable") == 0)
  122.                 {
  123.                         IGameVolumes::VolumeInfo volumeInfo;
  124.                         if (GetVolumeInfoForEntity(GetEntityId(), volumeInfo))
  125.                         {
  126.                                 for (uint32 i = 0; i < m_segments.size(); ++i)
  127.                                 {
  128.                                         SWaterSegment& segment = m_segments[i];
  129.  
  130.                                         if ((segment.m_pWaterArea == NULL) && (segment.m_pWaterRenderNode != NULL))
  131.                                         {
  132.                                                 if (!m_isRiver)
  133.                                                 {
  134.                                                         CreatePhysicsArea(i, m_baseMatrix, &volumeInfo.pVertices[0], volumeInfo.verticesCount, false, m_streamSpeed);
  135.                                                 }
  136.                                                 else
  137.                                                 {
  138.                                                         Vec3 vertices[4];
  139.                                                         FillOutRiverSegment(i, &volumeInfo.pVertices[0], volumeInfo.verticesCount, &vertices[0]);
  140.                                                         CreatePhysicsArea(i, m_baseMatrix, vertices, 4, true, m_streamSpeed);
  141.                                                 }
  142.  
  143.                                                 segment.m_pWaterRenderNode->SetMatrix(m_baseMatrix);
  144.                                         }
  145.                                 }
  146.  
  147.                                 AwakeAreaIfRequired(true);
  148.  
  149.                                 m_lastAwakeCheckPosition.zero();
  150.                         }
  151.                 }
  152.                 else if (strcmp(eventName, "PhysicsDisable") == 0)
  153.                 {
  154.                         DestroyPhysicsAreas();
  155.                 }
  156.         }
  157. }
  158.  
  159. void CGameVolume_Water::ProcessEvent(SEntityEvent& event)
  160. {
  161.         switch (event.event)
  162.         {
  163.         case ENTITY_EVENT_EDITOR_PROPERTY_CHANGED:
  164.                 {
  165.                         SetupVolume();
  166.                 }
  167.                 break;
  168.  
  169.         case ENTITY_EVENT_RESET:
  170.                 {
  171.                         // Only when exiting game mode
  172.                         if ((gEnv->IsEditor()) && (event.nParam[0] == 0))
  173.                         {
  174.                                 if (Matrix34::IsEquivalent(m_baseMatrix, m_initialMatrix) == false)
  175.                                 {
  176.                                         GetEntity()->SetWorldTM(m_initialMatrix);
  177.                                 }
  178.                         }
  179.                 }
  180.                 break;
  181.  
  182.         case ENTITY_EVENT_XFORM:
  183.                 {
  184.                         // Rotation requires to setup again
  185.                         // Internally the shape vertices are projected to a plane, and rotating changes that plane
  186.                         // Only allow rotations in the editor, at run time can be expensive
  187.                         if ((gEnv->IsEditing()) && (event.nParam[0] & ENTITY_XFORM_ROT))
  188.                         {
  189.                                 SetupVolume();
  190.                         }
  191.                         else if (event.nParam[0] & ENTITY_XFORM_POS)
  192.                         {
  193.                                 const Matrix34 entityWorldTM = GetEntity()->GetWorldTM();
  194.  
  195.                                 m_baseMatrix.SetTranslation(entityWorldTM.GetTranslation());
  196.  
  197.                                 for (uint32 i = 0; i < m_segments.size(); ++i)
  198.                                 {
  199.                                         SWaterSegment& segment = m_segments[i];
  200.  
  201.                                         UpdateRenderNode(segment.m_pWaterRenderNode, m_baseMatrix);
  202.  
  203.                                         if (segment.m_pWaterArea)
  204.                                         {
  205.                                                 const Vec3 newAreaPosition = m_baseMatrix.GetTranslation() + ((Quat(m_baseMatrix) * segment.m_physicsLocalAreaCenter) - segment.m_physicsLocalAreaCenter);
  206.  
  207.                                                 pe_params_pos position;
  208.                                                 position.pos = newAreaPosition;
  209.                                                 segment.m_pWaterArea->SetParams(&position);
  210.  
  211.                                                 pe_params_buoyancy pb;
  212.                                                 pb.waterPlane.origin = newAreaPosition;
  213.                                                 segment.m_pWaterArea->SetParams(&pb);
  214.  
  215.                                                 //gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere( areaPos.pos, 0.5f, ColorB(255, 0, 0));
  216.                                         }
  217.                                 }
  218.  
  219.                                 AwakeAreaIfRequired(false);
  220.                         }
  221.                 }
  222.                 break;
  223.  
  224.         case ENTITY_EVENT_HIDE:
  225.                 {
  226.                         AwakeAreaIfRequired(true);
  227.  
  228.                         WaterSegments::iterator iter = m_segments.begin();
  229.                         WaterSegments::iterator end = m_segments.end();
  230.                         while (iter != end)
  231.                         {
  232.                                 if (iter->m_pWaterRenderNode)
  233.                                 {
  234.                                         iter->m_pWaterRenderNode->Hide(true);
  235.                                 }
  236.  
  237.                                 ++iter;
  238.                         }
  239.  
  240.                         DestroyPhysicsAreas();
  241.                 }
  242.                 break;
  243.         case ENTITY_EVENT_UNHIDE:
  244.                 {
  245.                         IGameVolumes::VolumeInfo volumeInfo;
  246.                         if (GetVolumeInfoForEntity(GetEntityId(), volumeInfo))
  247.                         {
  248.                                 for (uint32 i = 0; i < m_segments.size(); ++i)
  249.                                 {
  250.                                         SWaterSegment& segment = m_segments[i];
  251.                                         if (segment.m_pWaterRenderNode)
  252.                                         {
  253.                                                 segment.m_pWaterRenderNode->Hide(false);
  254.  
  255.                                                 if (!m_isRiver)
  256.                                                 {
  257.                                                         CreatePhysicsArea(i, m_baseMatrix, &volumeInfo.pVertices[0], volumeInfo.verticesCount, false, m_streamSpeed);
  258.                                                 }
  259.                                                 else
  260.                                                 {
  261.                                                         Vec3 vertices[4];
  262.                                                         FillOutRiverSegment(i, &volumeInfo.pVertices[0], volumeInfo.verticesCount, &vertices[0]);
  263.                                                         CreatePhysicsArea(i, m_baseMatrix, vertices, 4, true, m_streamSpeed);
  264.                                                 }
  265.  
  266.                                                 segment.m_pWaterRenderNode->SetMatrix(m_baseMatrix);
  267.                                         }
  268.                                 }
  269.  
  270.                                 AwakeAreaIfRequired(true);
  271.  
  272.                                 m_lastAwakeCheckPosition.zero(); //After unhide, next movement will awake the area
  273.                         }
  274.  
  275.                 }
  276.                 break;
  277.         }
  278. }
  279.  
  280. uint64 CGameVolume_Water::GetEventMask() const
  281. {
  282.         return
  283.                 BIT64(ENTITY_EVENT_EDITOR_PROPERTY_CHANGED) |
  284.                 BIT64(ENTITY_EVENT_RESET) |
  285.                 BIT64(ENTITY_EVENT_XFORM) |
  286.                 BIT64(ENTITY_EVENT_HIDE) |
  287.                 BIT64(ENTITY_EVENT_UNHIDE);
  288. }
  289.  
  290. void CGameVolume_Water::GetMemoryUsage(ICrySizer* pSizer) const
  291. {
  292.         pSizer->AddObject(this, sizeof(*this));
  293. }
  294.  
  295. void CGameVolume_Water::CreateWaterRenderNode(IWaterVolumeRenderNode*& pWaterRenderNode)
  296. {
  297.         if (pWaterRenderNode == NULL)
  298.         {
  299.                 pWaterRenderNode = static_cast<IWaterVolumeRenderNode*>(gEnv->p3DEngine->CreateRenderNode(eERType_WaterVolume));
  300.                 pWaterRenderNode->SetAreaAttachedToEntity();
  301.         }
  302. }
  303.  
  304. void CGameVolume_Water::SetupVolume()
  305. {
  306.         IGameVolumes::VolumeInfo volumeInfo;
  307.         if (GetVolumeInfoForEntity(GetEntityId(), volumeInfo) == false)
  308.                 return;
  309.  
  310.         if (volumeInfo.verticesCount < 4)
  311.                 return;
  312.  
  313.         WaterProperties waterProperties(GetEntity());
  314.  
  315.         if (waterProperties.isRiver)
  316.         {
  317.                 if (volumeInfo.verticesCount % 2 != 0)
  318.                         return;
  319.  
  320.                 int numSegments = (volumeInfo.verticesCount / 2) - 1;
  321.  
  322.                 m_segments.resize(numSegments);
  323.  
  324.                 for (int i = 0; i < numSegments; ++i)
  325.                 {
  326.                         SetupVolumeSegment(waterProperties, i, &volumeInfo.pVertices[0], volumeInfo.verticesCount);
  327.                 }
  328.         }
  329.         else
  330.         {
  331.                 SetupVolumeSegment(waterProperties, 0, &volumeInfo.pVertices[0], volumeInfo.verticesCount);
  332.         }
  333.  
  334. #if CRY_PLATFORM_WINDOWS && !defined(_RELEASE)
  335.         {
  336.                 if (gEnv->IsEditor())
  337.                 {
  338.                         IEntity* pEnt = GetEntity();
  339.                         IMaterial* pMat = pEnt ? pEnt->GetMaterial() : 0;
  340.                         if (pMat)
  341.                         {
  342.                                 const SShaderItem& si = pMat->GetShaderItem();
  343.                                 if (si.m_pShader && si.m_pShader->GetShaderType() != eST_Water)
  344.                                 {
  345.                                         CryWarning(VALIDATOR_MODULE_3DENGINE, VALIDATOR_ERROR, "Incorrect shader set for water / water fog volume \"%s\"!", pEnt->GetName());
  346.                                 }
  347.                         }
  348.                 }
  349.         }
  350. #endif
  351.  
  352.         m_baseMatrix = GetEntity()->GetWorldTM();
  353.         m_initialMatrix = m_baseMatrix;
  354.         m_volumeDepth = waterProperties.depth;
  355.         m_streamSpeed = waterProperties.streamSpeed;
  356.         m_awakeAreaWhenMoving = waterProperties.awakeAreaWhenMoving;
  357.         m_isRiver = waterProperties.isRiver;
  358. }
  359.  
  360. void CGameVolume_Water::SetupVolumeSegment(const WaterProperties& waterProperties, const uint32 segmentIndex, const Vec3* pVertices, const uint32 vertexCount)
  361. {
  362.         SWaterSegment& segment = m_segments[segmentIndex];
  363.  
  364.         IWaterVolumeRenderNode*& pWaterRenderNode = segment.m_pWaterRenderNode;
  365.  
  366.         CreateWaterRenderNode(pWaterRenderNode);
  367.  
  368.         CRY_ASSERT(pWaterRenderNode != NULL);
  369.  
  370.         const Matrix34& entityWorldTM = GetEntity()->GetWorldTM();
  371.  
  372.         pWaterRenderNode->SetMinSpec(waterProperties.minSpec);
  373.         pWaterRenderNode->SetMaterialLayers((uint8)waterProperties.materialLayerMask);
  374.         pWaterRenderNode->SetViewDistRatio(waterProperties.viewDistanceRatio);
  375.  
  376.         Plane fogPlane;
  377.         fogPlane.SetPlane(Vec3Constants<float>::fVec3_OneZ, pVertices[0]);
  378.  
  379.         pWaterRenderNode->SetFogDensity(waterProperties.fogDensity);
  380.         pWaterRenderNode->SetFogColor(waterProperties.fogColor * max(waterProperties.fogColorMultiplier, 0.0f));
  381.         pWaterRenderNode->SetFogColorAffectedBySun(waterProperties.fogColorAffectedBySun);
  382.         pWaterRenderNode->SetFogShadowing(waterProperties.fogShadowing);
  383.         pWaterRenderNode->SetCapFogAtVolumeDepth(waterProperties.capFogAtVolumeDepth);
  384.  
  385.         pWaterRenderNode->SetCaustics(waterProperties.caustics);
  386.         pWaterRenderNode->SetCausticIntensity(waterProperties.causticIntensity);
  387.         pWaterRenderNode->SetCausticTiling(waterProperties.causticTiling);
  388.         pWaterRenderNode->SetCausticHeight(waterProperties.causticHeight);
  389.  
  390.         const Vec3* segmentVertices = pVertices;
  391.         uint32 segmentVertexCount = vertexCount;
  392.  
  393.         Vec3 vertices[4];
  394.  
  395.         if (waterProperties.isRiver)
  396.         {
  397.                 FillOutRiverSegment(segmentIndex, pVertices, vertexCount, &vertices[0]);
  398.  
  399.                 segmentVertices = &vertices[0];
  400.                 segmentVertexCount = 4;
  401.         }
  402.  
  403.         pWaterRenderNode->CreateArea(0, &segmentVertices[0], segmentVertexCount, Vec2(waterProperties.uScale, waterProperties.vScale), fogPlane, false);
  404.  
  405.         pWaterRenderNode->SetMaterial(GetEntity()->GetMaterial());
  406.         pWaterRenderNode->SetVolumeDepth(waterProperties.depth);
  407.         pWaterRenderNode->SetStreamSpeed(waterProperties.streamSpeed);
  408.  
  409.         CreatePhysicsArea(segmentIndex, entityWorldTM, segmentVertices, segmentVertexCount, waterProperties.isRiver, waterProperties.streamSpeed);
  410.  
  411.         // NOTE:
  412.         // Set the matrix after everything has been setup in local space
  413.         UpdateRenderNode(pWaterRenderNode, entityWorldTM);
  414. }
  415.  
  416. void CGameVolume_Water::CreatePhysicsArea(const uint32 segmentIndex, const Matrix34& baseMatrix, const Vec3* pVertices, uint32 vertexCount, const bool isRiver, const float streamSpeed)
  417. {
  418.         //Destroy previous physics if any
  419.         if (segmentIndex == 0)
  420.         {
  421.                 DestroyPhysicsAreas();
  422.         }
  423.  
  424.         SWaterSegment& segment = m_segments[segmentIndex];
  425.  
  426.         IWaterVolumeRenderNode* pWaterRenderNode = segment.m_pWaterRenderNode;
  427.         Vec3 waterFlow(ZERO);
  428.  
  429.         CRY_ASSERT(segment.m_pWaterArea == NULL);
  430.         CRY_ASSERT(pWaterRenderNode != NULL);
  431.  
  432.         pWaterRenderNode->SetMatrix(Matrix34::CreateIdentity());
  433.         segment.m_pWaterArea = pWaterRenderNode->SetAndCreatePhysicsArea(&pVertices[0], vertexCount);
  434.  
  435.         IPhysicalEntity* pWaterArea = segment.m_pWaterArea;
  436.         if (pWaterArea)
  437.         {
  438.                 const Quat entityWorldRot = Quat(baseMatrix);
  439.  
  440.                 pe_status_pos posStatus;
  441.                 pWaterArea->GetStatus(&posStatus);
  442.  
  443.                 const Vec3 areaPosition = baseMatrix.GetTranslation() + ((entityWorldRot * posStatus.pos) - posStatus.pos);
  444.  
  445.                 pe_params_pos position;
  446.                 position.pos = areaPosition;
  447.                 position.q = entityWorldRot;
  448.                 pWaterArea->SetParams(&position);
  449.  
  450.                 pe_params_buoyancy pb;
  451.                 pb.waterPlane.n = entityWorldRot * Vec3(0, 0, 1);
  452.                 pb.waterPlane.origin = areaPosition;
  453.  
  454.                 if (isRiver)
  455.                 {
  456.                         int i = segmentIndex;
  457.                         int j = vertexCount - 1 - segmentIndex;
  458.                         pb.waterFlow = ((pVertices[1] - pVertices[0]).GetNormalized() + (pVertices[2] - pVertices[3]).GetNormalized()) / 2.f * streamSpeed;
  459.                 }
  460.                 pWaterArea->SetParams(&pb);
  461.  
  462.                 pe_params_foreign_data pfd;
  463.                 pfd.pForeignData = pWaterRenderNode;
  464.                 pfd.iForeignData = PHYS_FOREIGN_ID_WATERVOLUME;
  465.                 pfd.iForeignFlags = 0;
  466.                 pWaterArea->SetParams(&pfd);
  467.  
  468.                 segment.m_physicsLocalAreaCenter = posStatus.pos;
  469.         }
  470. }
  471.  
  472. void CGameVolume_Water::DestroyPhysicsAreas()
  473. {
  474.         WaterSegments::iterator iter = m_segments.begin();
  475.         WaterSegments::iterator end = m_segments.end();
  476.         while (iter != end)
  477.         {
  478.                 if (iter->m_pWaterArea)
  479.                 {
  480.                         if (gEnv->pPhysicalWorld)
  481.                         {
  482.                                 gEnv->pPhysicalWorld->DestroyPhysicalEntity(iter->m_pWaterArea);
  483.                         }
  484.  
  485.                         iter->m_pWaterArea = NULL;
  486.                 }
  487.  
  488.                 ++iter;
  489.         }
  490.  
  491.         m_lastAwakeCheckPosition.zero();
  492. }
  493.  
  494. void CGameVolume_Water::AwakeAreaIfRequired(bool forceAwake)
  495. {
  496.         if (gEnv->IsEditing())
  497.                 return;
  498.  
  499.         if ((m_segments[0].m_pWaterArea == NULL) || (m_awakeAreaWhenMoving == false))
  500.                 return;
  501.  
  502.         const float thresholdSqr = (2.0f * 2.0f);
  503.         const float movedDistanceSqr = (m_baseMatrix.GetTranslation() - m_lastAwakeCheckPosition).len2();
  504.         if ((forceAwake == false) && (movedDistanceSqr <= thresholdSqr))
  505.                 return;
  506.  
  507.         m_lastAwakeCheckPosition = m_baseMatrix.GetTranslation();
  508.  
  509.         WaterSegments::iterator iter = m_segments.begin();
  510.         WaterSegments::iterator end = m_segments.end();
  511.         while (iter != end)
  512.         {
  513.                 CRY_ASSERT(iter->m_pWaterArea);
  514.                 pe_status_pos areaPos;
  515.                 iter->m_pWaterArea->GetStatus(&areaPos);
  516.  
  517.                 const Vec3 areaBoxCenter = areaPos.pos;
  518.                 IPhysicalEntity** pEntityList = NULL;
  519.  
  520.                 const int numberOfEntities = gEnv->pPhysicalWorld->GetEntitiesInBox(areaBoxCenter + areaPos.BBox[0], areaBoxCenter + areaPos.BBox[1], pEntityList, ent_sleeping_rigid | ent_rigid);
  521.  
  522.                 pe_action_awake awake;
  523.                 awake.bAwake = true;
  524.  
  525.                 for (int i = 0; i < numberOfEntities; ++i)
  526.                 {
  527.                         pEntityList[i]->Action(&awake);
  528.                 }
  529.  
  530.                 ++iter;
  531.         }
  532. }
  533.  
  534. void CGameVolume_Water::UpdateRenderNode(IWaterVolumeRenderNode* pWaterRenderNode, const Matrix34& newLocation)
  535. {
  536.         if (pWaterRenderNode)
  537.         {
  538.                 gEnv->p3DEngine->FreeRenderNodeState(pWaterRenderNode);
  539.  
  540.                 pWaterRenderNode->SetMatrix(newLocation);
  541.  
  542.                 gEnv->p3DEngine->RegisterEntity(pWaterRenderNode);
  543.         }
  544. }
  545.  
  546. void CGameVolume_Water::FillOutRiverSegment(const uint32 segmentIndex, const Vec3* pVertices, const uint32 vertexCount, Vec3* pVerticesOut)
  547. {
  548.         int i = segmentIndex;
  549.         int j = vertexCount - 1 - segmentIndex;
  550.  
  551.         pVerticesOut[0] = pVertices[i];
  552.         pVerticesOut[1] = pVertices[i + 1];
  553.         pVerticesOut[2] = pVertices[j - 1];
  554.         pVerticesOut[3] = pVertices[j];
  555. }
  556.  
  557. void CGameVolume_Water::DebugDrawVolume()
  558. {
  559.         IGameVolumes::VolumeInfo volumeInfo;
  560.         if (GetVolumeInfoForEntity(GetEntityId(), volumeInfo) == false)
  561.                 return;
  562.  
  563.         if (volumeInfo.verticesCount < 3)
  564.                 return;
  565.  
  566.         const Matrix34 worldTM = GetEntity()->GetWorldTM();
  567.         const Vec3 depthOffset = worldTM.GetColumn2().GetNormalized() * -m_volumeDepth;
  568.  
  569.         IRenderAuxGeom* pRenderAux = gEnv->pRenderer->GetIRenderAuxGeom();
  570.         for (uint32 i = 0; i < volumeInfo.verticesCount - 1; ++i)
  571.         {
  572.                 const Vec3 point1 = worldTM.TransformPoint(volumeInfo.pVertices[i]);
  573.                 const Vec3 point2 = worldTM.TransformPoint(volumeInfo.pVertices[i + 1]);
  574.  
  575.                 pRenderAux->DrawLine(point1, Col_SlateBlue, point1 + depthOffset, Col_SlateBlue, 2.0f);
  576.                 pRenderAux->DrawLine(point1 + depthOffset, Col_SlateBlue, point2 + depthOffset, Col_SlateBlue, 2.0f);
  577.         }
  578.  
  579.         const Vec3 firstPoint = worldTM.TransformPoint(volumeInfo.pVertices[0]);
  580.         const Vec3 lastPoint = worldTM.TransformPoint(volumeInfo.pVertices[volumeInfo.verticesCount - 1]);
  581.  
  582.         pRenderAux->DrawLine(lastPoint, Col_SlateBlue, lastPoint + depthOffset, Col_SlateBlue, 2.0f);
  583.         pRenderAux->DrawLine(lastPoint + depthOffset, Col_SlateBlue, firstPoint + depthOffset, Col_SlateBlue, 2.0f);
  584. }
  585.  
downloadGameVolume_Water.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