BVB Source Codes

CRYENGINE Show WaterVolumeRenderNode.cpp Source code

Return Download CRYENGINE: download WaterVolumeRenderNode.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 "WaterVolumeRenderNode.h"
  5. #include "VisAreas.h"
  6. #include "MatMan.h"
  7. #include "TimeOfDay.h"
  8. #include <CryMath/Cry_Geo.h>
  9. #include <CryThreading/IJobManager_JobDelegator.h>
  10.  
  11. DECLARE_JOB("CWaterVolume_Render", TCWaterVolume_Render, CWaterVolumeRenderNode::Render_JobEntry);
  12.  
  13. //////////////////////////////////////////////////////////////////////////
  14. // private triangulation code
  15. namespace WaterVolumeRenderNodeUtils
  16. {
  17. template<typename T>
  18. size_t PosOffset();
  19.  
  20. template<>
  21. size_t PosOffset<Vec3>()
  22. {
  23.         return 0;
  24. }
  25.  
  26. template<>
  27. size_t PosOffset<SVF_P3F_C4B_T2F>()
  28. {
  29.         return offsetof(SVF_P3F_C4B_T2F, xyz);
  30. }
  31.  
  32. template<typename T>
  33. struct VertexAccess
  34. {
  35.         VertexAccess(const T* pVertices, size_t numVertices)
  36.                 : m_pVertices(pVertices)
  37.                 , m_numVertices(numVertices)
  38.         {
  39.         }
  40.  
  41.         const Vec3& operator[](size_t idx) const
  42.         {
  43.                 assert(idx < m_numVertices);
  44.                 const T* pVertex = &m_pVertices[idx];
  45.                 return *(Vec3*) ((size_t) pVertex + PosOffset<T>());
  46.         }
  47.  
  48.         const size_t GetNumVertices() const
  49.         {
  50.                 return m_numVertices;
  51.         }
  52.  
  53. private:
  54.         const T* m_pVertices;
  55.         size_t   m_numVertices;
  56. };
  57.  
  58. template<typename T>
  59. float Area(const VertexAccess<T>& contour)
  60. {
  61.         int n = contour.GetNumVertices();
  62.         float area = 0.0f;
  63.  
  64.         for (int p = n - 1, q = 0; q < n; p = q++)
  65.                 area += contour[p].x * contour[q].y - contour[q].x * contour[p].y;
  66.  
  67.         return area * 0.5f;
  68. }
  69.  
  70. bool InsideTriangle(float Ax, float Ay, float Bx, float By, float Cx, float Cy, float Px, float Py)
  71. {
  72.         float ax = Cx - Bx;
  73.         float ay = Cy - By;
  74.         float bx = Ax - Cx;
  75.         float by = Ay - Cy;
  76.         float cx = Bx - Ax;
  77.         float cy = By - Ay;
  78.         float apx = Px - Ax;
  79.         float apy = Py - Ay;
  80.         float bpx = Px - Bx;
  81.         float bpy = Py - By;
  82.         float cpx = Px - Cx;
  83.         float cpy = Py - Cy;
  84.  
  85.         float aCROSSbp = ax * bpy - ay * bpx;
  86.         float cCROSSap = cx * apy - cy * apx;
  87.         float bCROSScp = bx * cpy - by * cpx;
  88.  
  89.         const float fEpsilon = -0.01f;
  90.         return (aCROSSbp >= fEpsilon) && (bCROSScp >= fEpsilon) && (cCROSSap >= fEpsilon);
  91. };
  92.  
  93. template<typename T, typename S>
  94. bool Snip(const VertexAccess<T>& contour, int u, int v, int w, int n, const S* V)
  95. {
  96.         float Ax = contour[V[u]].x;
  97.         float Ay = contour[V[u]].y;
  98.  
  99.         float Bx = contour[V[v]].x;
  100.         float By = contour[V[v]].y;
  101.  
  102.         float Cx = contour[V[w]].x;
  103.         float Cy = contour[V[w]].y;
  104.  
  105.         if ((((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax))) < 1e-6f)
  106.                 return false;
  107.  
  108.         for (int p = 0; p < n; p++)
  109.         {
  110.                 if ((p == u) || (p == v) || (p == w))
  111.                         continue;
  112.  
  113.                 float Px = contour[V[p]].x;
  114.                 float Py = contour[V[p]].y;
  115.  
  116.                 if (WaterVolumeRenderNodeUtils::InsideTriangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py))
  117.                         return false;
  118.         }
  119.  
  120.         return true;
  121. }
  122.  
  123. template<typename T, typename S>
  124. bool Triangulate(const VertexAccess<T>& contour, std::vector<S>& result)
  125. {
  126.         // reset result
  127.         result.resize(0);
  128.  
  129.         //C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
  130.         PREFAST_SUPPRESS_WARNING(6255)
  131.         // allocate and initialize list of vertices in polygon
  132.         int n = contour.GetNumVertices();
  133.         if (n < 3)
  134.                 return false;
  135.  
  136.         S* V = (S*) alloca(n * sizeof(S));
  137.  
  138.         // we want a counter-clockwise polygon in V
  139.         if (0.0f < Area(contour))
  140.                 for (int v = 0; v < n; v++)
  141.                         V[v] = v;
  142.         else
  143.                 for (int v = 0; v < n; v++)
  144.                         V[v] = (n - 1) - v;
  145.  
  146.         int nv = n;
  147.  
  148.         //  remove nv-2 vertices, creating 1 triangle every time
  149.         int count = 2 * nv;     // error detection
  150.  
  151.         for (int m = 0, v = nv - 1; nv > 2; )
  152.         {
  153.                 // if we loop, it is probably a non-simple polygon
  154.                 if (0 >= (count--))
  155.                         return false;   // ERROR - probably bad polygon!
  156.  
  157.                 // three consecutive vertices in current polygon, <u,v,w>
  158.                 int u = v;
  159.                 if (nv <= u) u = 0;                 // previous
  160.                 v = u + 1;
  161.                 if (nv <= v) v = 0;                 // new v
  162.                 int w = v + 1;
  163.                 if (nv <= w) w = 0;                 // next
  164.  
  165.                 if (Snip(contour, u, v, w, nv, V))
  166.                 {
  167.                         // true names of the vertices
  168.                         PREFAST_SUPPRESS_WARNING(6385)
  169.                         S a = V[u];
  170.                         S b = V[v];
  171.                         S c = V[w];
  172.  
  173.                         // output triangle
  174.                         result.push_back(a);
  175.                         result.push_back(b);
  176.                         result.push_back(c);
  177.  
  178.                         m++;
  179.  
  180.                         // remove v from remaining polygon
  181.                         for (int s = v, t = v + 1; t < nv; s++, t++)
  182.                         {
  183.                                 PREFAST_SUPPRESS_WARNING(6386)
  184.                                 V[s] = V[t];
  185.                         }
  186.  
  187.                         nv--;
  188.  
  189.                         // reset error detection counter
  190.                         count = 2 * nv;
  191.                 }
  192.         }
  193.  
  194.         return true;
  195. }
  196. }
  197.  
  198. //////////////////////////////////////////////////////////////////////////
  199. // helpers
  200.  
  201. inline static Vec3 MapVertexToFogPlane(const Vec3& v, const Plane& p)
  202. {
  203.         const Vec3 projDir(0, 0, 1);
  204.         float perpdist = p | v;
  205.         float cosine = p.n | projDir;
  206.         assert(fabs(cosine) > 1e-4);
  207.         float pd_c = -perpdist / cosine;
  208.         return v + projDir * pd_c;
  209. }
  210.  
  211. //////////////////////////////////////////////////////////////////////////
  212. // CWaterVolumeRenderNode implementation
  213.  
  214. CWaterVolumeRenderNode::CWaterVolumeRenderNode()
  215.         : m_volumeType(IWaterVolumeRenderNode::eWVT_Unknown)
  216.         , m_volumeID(~0)
  217.         , m_volumeDepth(0)
  218.         , m_streamSpeed(0)
  219.         , m_wvParams()
  220.         , m_pSerParams(nullptr)
  221.         , m_pPhysAreaInput(nullptr)
  222.         , m_pPhysArea(nullptr)
  223.         , m_parentEntityWorldTM(IDENTITY)
  224.         , m_nLayerId(0)
  225.         , m_fogDensity(0.0f)
  226.         , m_fogColor(0.2f, 0.5f, 0.7f)
  227.         , m_fogColorAffectedBySun(true)
  228.         , m_fogShadowing(0.5f)
  229.         , m_fogPlane(Vec3(0, 0, 1), 0)
  230.         , m_fogPlaneBase(Vec3(0, 0, 1), 0)
  231.         , m_vOffset(ZERO)
  232.         , m_center(ZERO)
  233.         , m_WSBBox(Vec3(-1), Vec3(1))
  234.         , m_capFogAtVolumeDepth(false)
  235.         , m_attachedToEntity(false)
  236.         , m_caustics(true)
  237.         , m_causticIntensity(1.0f)
  238.         , m_causticTiling(1.0f)
  239.         , m_causticShadow(0.0f)
  240.         , m_causticHeight(0.5f)
  241. {
  242.         GetInstCount(GetRenderNodeType())++;
  243.  
  244.         m_pWaterBodyIntoMat = GetMatMan()->LoadMaterial("EngineAssets/Materials/Fog/WaterFogVolumeInto", false);
  245.         m_pWaterBodyOutofMat = GetMatMan()->LoadMaterial("EngineAssets/Materials/Fog/WaterFogVolumeOutof", false);
  246.         for (int i = 0; i < RT_COMMAND_BUF_COUNT; ++i)
  247.         {
  248.                 m_pVolumeRE[i] = GetRenderer() ?
  249.                                  static_cast<CREWaterVolume*>(GetRenderer()->EF_CreateRE(eDATA_WaterVolume)) : nullptr;
  250.                 if (m_pVolumeRE[i])
  251.                 {
  252.                         m_pVolumeRE[i]->m_drawWaterSurface = false;
  253.                         m_pVolumeRE[i]->m_pParams = &m_wvParams[i];
  254.                 }
  255.         }
  256.         for (int i = 0; i < RT_COMMAND_BUF_COUNT; ++i)
  257.         {
  258.                 m_pSurfaceRE[i] = GetRenderer() ?
  259.                                   static_cast<CREWaterVolume*>(GetRenderer()->EF_CreateRE(eDATA_WaterVolume)) : nullptr;
  260.                 if (m_pSurfaceRE[i])
  261.                 {
  262.                         m_pSurfaceRE[i]->m_drawWaterSurface = true;
  263.                         m_pSurfaceRE[i]->m_pParams = &m_wvParams[i];
  264.                 }
  265.         }
  266. }
  267.  
  268. CWaterVolumeRenderNode::~CWaterVolumeRenderNode()
  269. {
  270.         GetInstCount(GetRenderNodeType())--;
  271.  
  272.         Dephysicalize();
  273.  
  274.         for (int i = 0; i < RT_COMMAND_BUF_COUNT; ++i)
  275.         {
  276.                 if (m_pVolumeRE[i])
  277.                 {
  278.                         m_pVolumeRE[i]->Release(true);
  279.                         m_pVolumeRE[i] = 0;
  280.                 }
  281.                 if (m_pSurfaceRE[i])
  282.                 {
  283.                         m_pSurfaceRE[i]->Release(true);
  284.                         m_pSurfaceRE[i] = 0;
  285.                 }
  286.         }
  287.         SAFE_DELETE(m_pSerParams);
  288.         SAFE_DELETE(m_pPhysAreaInput);
  289.  
  290.         Get3DEngine()->FreeRenderNodeState(this);
  291. }
  292.  
  293. void CWaterVolumeRenderNode::SetAreaAttachedToEntity()
  294. {
  295.         m_attachedToEntity = true;
  296. }
  297.  
  298. void CWaterVolumeRenderNode::SetFogDensity(float fogDensity)
  299. {
  300.         m_fogDensity = fogDensity;
  301. }
  302.  
  303. float CWaterVolumeRenderNode::GetFogDensity() const
  304. {
  305.         return m_fogDensity;
  306. }
  307.  
  308. void CWaterVolumeRenderNode::SetFogColor(const Vec3& fogColor)
  309. {
  310.         m_fogColor = fogColor;
  311. }
  312.  
  313. void CWaterVolumeRenderNode::SetFogColorAffectedBySun(bool enable)
  314. {
  315.         m_fogColorAffectedBySun = enable;
  316. }
  317.  
  318. void CWaterVolumeRenderNode::SetFogShadowing(float fogShadowing)
  319. {
  320.         m_fogShadowing = fogShadowing;
  321. }
  322.  
  323. void CWaterVolumeRenderNode::SetCapFogAtVolumeDepth(bool capFog)
  324. {
  325.         m_capFogAtVolumeDepth = capFog;
  326. }
  327.  
  328. void CWaterVolumeRenderNode::SetVolumeDepth(float volumeDepth)
  329. {
  330.         m_volumeDepth = volumeDepth;
  331.  
  332.         UpdateBoundingBox();
  333. }
  334.  
  335. void CWaterVolumeRenderNode::SetStreamSpeed(float streamSpeed)
  336. {
  337.         m_streamSpeed = streamSpeed;
  338. }
  339.  
  340. void CWaterVolumeRenderNode::SetCaustics(bool caustics)
  341. {
  342.         m_caustics = caustics;
  343. }
  344.  
  345. void CWaterVolumeRenderNode::SetCausticIntensity(float causticIntensity)
  346. {
  347.         m_causticIntensity = causticIntensity;
  348. }
  349.  
  350. void CWaterVolumeRenderNode::SetCausticTiling(float causticTiling)
  351. {
  352.         m_causticTiling = causticTiling;
  353. }
  354.  
  355. void CWaterVolumeRenderNode::SetCausticHeight(float causticHeight)
  356. {
  357.         m_causticHeight = causticHeight;
  358. }
  359.  
  360. void CWaterVolumeRenderNode::CreateOcean(uint64 volumeID, /* TBD */ bool keepSerializationParams)
  361. {
  362. }
  363.  
  364. void CWaterVolumeRenderNode::CreateArea(uint64 volumeID, const Vec3* pVertices, unsigned int numVertices, const Vec2& surfUVScale, const Plane& fogPlane, bool keepSerializationParams, int nSID)
  365. {
  366.         const bool serializeWith3DEngine = keepSerializationParams && !IsAttachedToEntity();
  367.  
  368.         assert(fabs(fogPlane.n.GetLengthSquared() - 1.0f) < 1e-4 && "CWaterVolumeRenderNode::CreateArea(...) -- Fog plane normal doesn't have unit length!");
  369.         assert(fogPlane.n.Dot(Vec3(0, 0, 1)) > 1e-4f && "CWaterVolumeRenderNode::CreateArea(...) -- Invalid fog plane specified!");
  370.         if (fogPlane.n.Dot(Vec3(0, 0, 1)) <= 1e-4f)
  371.                 return;
  372.  
  373.         assert(numVertices >= 3);
  374.         if (numVertices < 3)
  375.                 return;
  376.  
  377.         m_volumeID = volumeID;
  378.         m_fogPlane = fogPlane;
  379.         m_fogPlaneBase = fogPlane;
  380.         m_volumeType = IWaterVolumeRenderNode::eWVT_Area;
  381.  
  382.         // copy volatile creation params to be able to serialize water volume if needed (only in editor)
  383.         if (serializeWith3DEngine)
  384.                 CopyVolatileAreaSerParams(pVertices, numVertices, surfUVScale);
  385.  
  386.         // remove form 3d engine
  387.         Get3DEngine()->UnRegisterEntityAsJob(this);
  388.  
  389.         // Edges pre-pass - break into smaller edges, in case distance threshold too big
  390.         PodArray<Vec3> pTessVertList;
  391.         PodArray<SVF_P3F_C4B_T2F> pVertsTemp;
  392.         PodArray<uint16> pIndicesTemp;
  393.  
  394.         for (uint32 v(0); v < numVertices; ++v)
  395.         {
  396.                 Vec3 in_a = pVertices[v];
  397.                 Vec3 in_b = (v < numVertices - 1) ? pVertices[v + 1] : pVertices[0]; // close mesh
  398.  
  399.                 Vec3 vAB = in_b - in_a;
  400.                 float fLenAB = vAB.len();
  401.                 vAB.normalize();
  402.  
  403.                 pTessVertList.push_back(in_a);
  404.  
  405.                 const float fLenThreshold = 100.0f;  // break every 100 meters
  406.                 Vec3 vNewVert = Vec3(in_a + (vAB * fLenThreshold));
  407.                 while (fLenAB > fLenThreshold)
  408.                 {
  409.                         pTessVertList.push_back(vNewVert);
  410.  
  411.                         vNewVert = Vec3(vNewVert + (vAB * fLenThreshold));
  412.                         vAB = in_b - vNewVert;
  413.                         fLenAB = vAB.len();
  414.                         vAB.normalize();
  415.                 }
  416.         }
  417.  
  418.         m_waterSurfaceVertices.resize(pTessVertList.size());
  419.         for (uint32 i = 0; i < pTessVertList.size(); ++i)
  420.         {
  421.                 // project input vertex onto fog plane
  422.                 m_waterSurfaceVertices[i].xyz = MapVertexToFogPlane(pTessVertList[i], fogPlane);
  423.  
  424.                 // generate texture coordinates
  425.                 m_waterSurfaceVertices[i].st = Vec2(surfUVScale.x * (pTessVertList[i].x - pTessVertList[0].x), surfUVScale.y * (pTessVertList[i].y - pTessVertList[0].y));
  426.  
  427.                 pVertsTemp.push_back(m_waterSurfaceVertices[i]);
  428.         }
  429.  
  430.         // generate indices.
  431.         //      Note: triangulation code not robust, relies on contour/vertices to be declared sequentially and no holes -> too many vertices will lead to stretched results
  432.         WaterVolumeRenderNodeUtils::Triangulate(WaterVolumeRenderNodeUtils::VertexAccess<SVF_P3F_C4B_T2F>(&m_waterSurfaceVertices[0], m_waterSurfaceVertices.size()), m_waterSurfaceIndices);
  433.  
  434.         // update bounding info
  435.         UpdateBoundingBox();
  436.  
  437.         // Safety check.
  438.         if (m_waterSurfaceIndices.empty())
  439.                 return;
  440.  
  441.         // Pre-tessellate mesh further
  442.         uint32 nIterations = 4;
  443.         for (uint32 i = 0; i < nIterations; ++i)
  444.         {
  445.                 uint32 nIndices = m_waterSurfaceIndices.size();
  446.                 for (uint32 t = 0; t < nIndices; t += 3)
  447.                 {
  448.                         // Get triangle, compute median edge vertex, insert to vertex list
  449.                         uint16 id_a = m_waterSurfaceIndices[t + 0];
  450.                         uint16 id_b = m_waterSurfaceIndices[t + 1];
  451.                         uint16 id_c = m_waterSurfaceIndices[t + 2];
  452.  
  453.                         SVF_P3F_C4B_T2F& vtx_a = m_waterSurfaceVertices[id_a];
  454.                         SVF_P3F_C4B_T2F& vtx_b = m_waterSurfaceVertices[id_b];
  455.                         SVF_P3F_C4B_T2F& vtx_c = m_waterSurfaceVertices[id_c];
  456.  
  457.                         SVF_P3F_C4B_T2F vtx_m_ab;
  458.                         vtx_m_ab.xyz = (vtx_a.xyz + vtx_b.xyz) * 0.5f;
  459.                         vtx_m_ab.st = (vtx_a.st + vtx_b.st) * 0.5f;
  460.                         vtx_m_ab.color = vtx_a.color;
  461.  
  462.                         pVertsTemp.push_back(vtx_m_ab);
  463.                         uint16 id_d = (uint16) pVertsTemp.size() - 1;
  464.  
  465.                         SVF_P3F_C4B_T2F vtx_m_bc;
  466.                         vtx_m_bc.xyz = (vtx_b.xyz + vtx_c.xyz) * 0.5f;
  467.                         vtx_m_bc.st = (vtx_b.st + vtx_c.st) * 0.5f;
  468.                         vtx_m_bc.color = vtx_a.color;
  469.  
  470.                         pVertsTemp.push_back(vtx_m_bc);
  471.                         uint16 id_e = (uint16) pVertsTemp.size() - 1;
  472.  
  473.                         SVF_P3F_C4B_T2F vtx_m_ca;
  474.                         vtx_m_ca.xyz = (vtx_a.xyz + vtx_c.xyz) * 0.5f;
  475.                         vtx_m_ca.st = (vtx_a.st + vtx_c.st) * 0.5f;
  476.                         vtx_m_ca.color = vtx_a.color;
  477.  
  478.                         pVertsTemp.push_back(vtx_m_ca);
  479.                         uint16 id_f = (uint16) pVertsTemp.size() - 1;
  480.  
  481.                         // build new indices
  482.  
  483.                         // aed
  484.                         pIndicesTemp.push_back(id_a);
  485.                         pIndicesTemp.push_back(id_d);
  486.                         pIndicesTemp.push_back(id_f);
  487.  
  488.                         // ebd
  489.                         pIndicesTemp.push_back(id_d);
  490.                         pIndicesTemp.push_back(id_b);
  491.                         pIndicesTemp.push_back(id_e);
  492.  
  493.                         // bfd
  494.                         pIndicesTemp.push_back(id_f);
  495.                         pIndicesTemp.push_back(id_d);
  496.                         pIndicesTemp.push_back(id_e);
  497.  
  498.                         // fcd
  499.                         pIndicesTemp.push_back(id_f);
  500.                         pIndicesTemp.push_back(id_e);
  501.                         pIndicesTemp.push_back(id_c);
  502.                 }
  503.  
  504.                 // update index list for new iteration
  505.                 m_waterSurfaceIndices.resize(pIndicesTemp.size());
  506.                 memcpy(&m_waterSurfaceIndices[0], &pIndicesTemp[0], sizeof(uint16) * pIndicesTemp.size());
  507.                 m_waterSurfaceVertices.resize(pVertsTemp.size());
  508.                 memcpy(&m_waterSurfaceVertices[0], &pVertsTemp[0], sizeof(SVF_P3F_C4B_T2F) * pVertsTemp.size());
  509.                 pIndicesTemp.clear();
  510.         }
  511.  
  512.         // update reference to vertex and index buffer
  513.         for (int i = 0; i < RT_COMMAND_BUF_COUNT; ++i)
  514.         {
  515.                 m_wvParams[i].m_pVertices = &m_waterSurfaceVertices[0];
  516.                 m_wvParams[i].m_numVertices = m_waterSurfaceVertices.size();
  517.                 m_wvParams[i].m_pIndices = &m_waterSurfaceIndices[0];
  518.                 m_wvParams[i].m_numIndices = m_waterSurfaceIndices.size();
  519.         }
  520.  
  521.         // add to 3d engine
  522.         Get3DEngine()->RegisterEntity(this, nSID, nSID);
  523. }
  524.  
  525. void CWaterVolumeRenderNode::CreateRiver(uint64 volumeID, const Vec3* pVertices, unsigned int numVertices, float uTexCoordBegin, float uTexCoordEnd, const Vec2& surfUVScale, const Plane& fogPlane, bool keepSerializationParams, int nSID)
  526. {
  527.         assert(fabs(fogPlane.n.GetLengthSquared() - 1.0f) < 1e-4 && "CWaterVolumeRenderNode::CreateRiver(...) -- Fog plane normal doesn't have unit length!");
  528.         assert(fogPlane.n.Dot(Vec3(0, 0, 1)) > 1e-4f && "CWaterVolumeRenderNode::CreateRiver(...) -- Invalid fog plane specified!");
  529.         if (fogPlane.n.Dot(Vec3(0, 0, 1)) <= 1e-4f)
  530.                 return;
  531.  
  532.         assert(numVertices == 4);
  533.         if (numVertices != 4 || !_finite(pVertices[0].x) || !_finite(pVertices[1].x) || !_finite(pVertices[2].x) || !_finite(pVertices[3].x))
  534.                 return;
  535.  
  536.         m_volumeID = volumeID;
  537.         m_fogPlane = fogPlane;
  538.         m_fogPlaneBase = fogPlane;
  539.         m_volumeType = IWaterVolumeRenderNode::eWVT_River;
  540.  
  541.         // copy volatile creation params to be able to serialize water volume if needed (only in editor)
  542.         if (keepSerializationParams)
  543.                 CopyVolatileRiverSerParams(pVertices, numVertices, uTexCoordBegin, uTexCoordEnd, surfUVScale);
  544.  
  545.         // remove form 3d engine
  546.         Get3DEngine()->UnRegisterEntityAsJob(this);
  547.  
  548.         // generate vertices
  549.         m_waterSurfaceVertices.resize(5);
  550.         m_waterSurfaceVertices[0].xyz = pVertices[0];
  551.         m_waterSurfaceVertices[1].xyz = pVertices[1];
  552.         m_waterSurfaceVertices[2].xyz = pVertices[2];
  553.         m_waterSurfaceVertices[3].xyz = pVertices[3];
  554.         m_waterSurfaceVertices[4].xyz = 0.25f * (pVertices[0] + pVertices[1] + pVertices[2] + pVertices[3]);
  555.  
  556.         Vec3 tv0 = Vec3(0, 0, 1.f);
  557.         Vec3 tv1 = Vec3(0, 0, -1.f);
  558.         Plane planes[4];
  559.         planes[0].SetPlane(pVertices[0], pVertices[1], pVertices[1] + tv0);
  560.         planes[1].SetPlane(pVertices[2], pVertices[3], pVertices[3] + tv1);
  561.         planes[2].SetPlane(pVertices[0], pVertices[2], pVertices[2] + tv1);
  562.         planes[3].SetPlane(pVertices[1], pVertices[3], pVertices[3] + tv0);
  563.  
  564.         for (uint32 i(0); i < 5; ++i)
  565.         {
  566.                 // map input vertex onto fog plane
  567.                 m_waterSurfaceVertices[i].xyz = MapVertexToFogPlane(m_waterSurfaceVertices[i].xyz, fogPlane);
  568.  
  569.                 // generate texture coordinates
  570.                 float d0(planes[0].DistFromPlane(m_waterSurfaceVertices[i].xyz));
  571.                 float d1(planes[1].DistFromPlane(m_waterSurfaceVertices[i].xyz));
  572.                 float d2(planes[2].DistFromPlane(m_waterSurfaceVertices[i].xyz));
  573.                 float d3(planes[3].DistFromPlane(m_waterSurfaceVertices[i].xyz));
  574.                 float t(fabsf(d0 + d1) < FLT_EPSILON ? 0.0f : d0 / (d0 + d1));
  575.  
  576.                 Vec2 st = Vec2((1 - t) * fabsf(uTexCoordBegin) + t * fabsf(uTexCoordEnd), fabsf(d2 + d3) < FLT_EPSILON ? 0.0f : d2 / (d2 + d3));
  577.                 st[0] *= surfUVScale.x;
  578.                 st[1] *= surfUVScale.y;
  579.  
  580.                 m_waterSurfaceVertices[i].st = st;
  581.         }
  582.  
  583.         // generate indices
  584.         m_waterSurfaceIndices.resize(12);
  585.         m_waterSurfaceIndices[0] = 0;
  586.         m_waterSurfaceIndices[1] = 1;
  587.         m_waterSurfaceIndices[2] = 4;
  588.  
  589.         m_waterSurfaceIndices[3] = 1;
  590.         m_waterSurfaceIndices[4] = 3;
  591.         m_waterSurfaceIndices[5] = 4;
  592.  
  593.         m_waterSurfaceIndices[6] = 3;
  594.         m_waterSurfaceIndices[7] = 2;
  595.         m_waterSurfaceIndices[8] = 4;
  596.  
  597.         m_waterSurfaceIndices[9] = 0;
  598.         m_waterSurfaceIndices[10] = 4;
  599.         m_waterSurfaceIndices[11] = 2;
  600.  
  601.         // update bounding info
  602.         UpdateBoundingBox();
  603.  
  604.         // update reference to vertex and index buffer
  605.         for (int i = 0; i < RT_COMMAND_BUF_COUNT; ++i)
  606.         {
  607.                 m_wvParams[i].m_pVertices = &m_waterSurfaceVertices[0];
  608.                 m_wvParams[i].m_numVertices = m_waterSurfaceVertices.size();
  609.                 m_wvParams[i].m_pIndices = &m_waterSurfaceIndices[0];
  610.                 m_wvParams[i].m_numIndices = m_waterSurfaceIndices.size();
  611.         }
  612.  
  613.         // add to 3d engine
  614.         Get3DEngine()->RegisterEntity(this, nSID, nSID);
  615. }
  616.  
  617. void CWaterVolumeRenderNode::SetAreaPhysicsArea(const Vec3* pVertices, unsigned int numVertices, bool keepSerializationParams)
  618. {
  619.         const bool serializeWith3DEngine = keepSerializationParams && !IsAttachedToEntity();
  620.  
  621.         assert(pVertices && numVertices > 3 && m_volumeType == IWaterVolumeRenderNode::eWVT_Area);
  622.         if (!pVertices || numVertices <= 3 || m_volumeType != IWaterVolumeRenderNode::eWVT_Area)
  623.                 return;
  624.  
  625.         if (!m_pPhysAreaInput)
  626.                 m_pPhysAreaInput = new SWaterVolumePhysAreaInput;
  627.  
  628.         const Plane& fogPlane(m_fogPlane);
  629.  
  630.         // generate contour vertices
  631.         m_pPhysAreaInput->m_contour.resize(numVertices);
  632.  
  633.         // map input vertices onto fog plane
  634.         if (WaterVolumeRenderNodeUtils::Area(WaterVolumeRenderNodeUtils::VertexAccess<Vec3>(pVertices, numVertices)) > 0.0f)
  635.         {
  636.                 for (unsigned int i(0); i < numVertices; ++i)
  637.                         m_pPhysAreaInput->m_contour[i] = MapVertexToFogPlane(pVertices[i], fogPlane);   // flip vertex order as physics expects them CCW
  638.         }
  639.         else
  640.         {
  641.                 for (unsigned int i(0); i < numVertices; ++i)
  642.                         m_pPhysAreaInput->m_contour[i] = MapVertexToFogPlane(pVertices[numVertices - 1 - i], fogPlane);
  643.         }
  644.  
  645.         // triangulate contour
  646.         WaterVolumeRenderNodeUtils::Triangulate(WaterVolumeRenderNodeUtils::VertexAccess<Vec3>(&m_pPhysAreaInput->m_contour[0], m_pPhysAreaInput->m_contour.size()), m_pPhysAreaInput->m_indices);
  647.  
  648.         // reset flow
  649.         m_pPhysAreaInput->m_flowContour.resize(0);
  650.  
  651.         if (serializeWith3DEngine)
  652.                 CopyVolatilePhysicsAreaContourSerParams(pVertices, numVertices);
  653. }
  654.  
  655. void CWaterVolumeRenderNode::SetRiverPhysicsArea(const Vec3* pVertices, unsigned int numVertices, bool keepSerializationParams)
  656. {
  657.         assert(pVertices && numVertices > 3 && !(numVertices & 1) && m_volumeType == IWaterVolumeRenderNode::eWVT_River);
  658.         if (!pVertices || numVertices <= 3 || (numVertices & 1) || m_volumeType != IWaterVolumeRenderNode::eWVT_River)
  659.                 return;
  660.  
  661.         if (!m_pPhysAreaInput)
  662.                 m_pPhysAreaInput = new SWaterVolumePhysAreaInput;
  663.  
  664.         const Plane& fogPlane(m_fogPlane);
  665.  
  666.         // generate contour vertices
  667.         m_pPhysAreaInput->m_contour.resize(numVertices);
  668.  
  669.         // map input vertices onto fog plane
  670.         if (WaterVolumeRenderNodeUtils::Area(WaterVolumeRenderNodeUtils::VertexAccess<Vec3>(pVertices, numVertices)) > 0.0f)
  671.         {
  672.                 for (unsigned int i(0); i < numVertices; ++i)
  673.                         m_pPhysAreaInput->m_contour[i] = MapVertexToFogPlane(pVertices[i], fogPlane);   // flip vertex order as physics expects them CCW
  674.         }
  675.         else
  676.         {
  677.                 for (unsigned int i(0); i < numVertices; ++i)
  678.                         m_pPhysAreaInput->m_contour[i] = MapVertexToFogPlane(pVertices[numVertices - 1 - i], fogPlane);
  679.         }
  680.  
  681.         // generate flow along contour
  682.         unsigned int h(numVertices / 2);
  683.         unsigned int h2(numVertices);
  684.         m_pPhysAreaInput->m_flowContour.resize(numVertices);
  685.         for (unsigned int i(0); i < h; ++i)
  686.         {
  687.                 if (!i)
  688.                         m_pPhysAreaInput->m_flowContour[i] = (m_pPhysAreaInput->m_contour[i + 1] - m_pPhysAreaInput->m_contour[i]).GetNormalizedSafe() * m_streamSpeed;
  689.                 else if (i == h - 1)
  690.                         m_pPhysAreaInput->m_flowContour[i] = (m_pPhysAreaInput->m_contour[i] - m_pPhysAreaInput->m_contour[i - 1]).GetNormalizedSafe() * m_streamSpeed;
  691.                 else
  692.                         m_pPhysAreaInput->m_flowContour[i] = (m_pPhysAreaInput->m_contour[i + 1] - m_pPhysAreaInput->m_contour[i - 1]).GetNormalizedSafe() * m_streamSpeed;
  693.         }
  694.  
  695.         for (unsigned int i(0); i < h; ++i)
  696.         {
  697.                 if (!i)
  698.                         m_pPhysAreaInput->m_flowContour[h2 - 1 - i] = (m_pPhysAreaInput->m_contour[h2 - 1 - i - 1] - m_pPhysAreaInput->m_contour[h2 - 1 - i]).GetNormalizedSafe() * m_streamSpeed;
  699.                 else if (i == h - 1)
  700.                         m_pPhysAreaInput->m_flowContour[h2 - 1 - i] = (m_pPhysAreaInput->m_contour[h2 - 1 - i] - m_pPhysAreaInput->m_contour[h2 - 1 - i + 1]).GetNormalizedSafe() * m_streamSpeed;
  701.                 else
  702.                         m_pPhysAreaInput->m_flowContour[h2 - 1 - i] = (m_pPhysAreaInput->m_contour[h2 - 1 - i - 1] - m_pPhysAreaInput->m_contour[h2 - 1 - i + 1]).GetNormalizedSafe() * m_streamSpeed;
  703.         }
  704.  
  705.         // triangulate contour
  706.         m_pPhysAreaInput->m_indices.resize(3 * 2 * (numVertices / 2 - 1));
  707.         for (unsigned int i(0); i < h - 1; ++i)
  708.         {
  709.                 m_pPhysAreaInput->m_indices[6 * i + 0] = i;
  710.                 m_pPhysAreaInput->m_indices[6 * i + 1] = i + 1;
  711.                 m_pPhysAreaInput->m_indices[6 * i + 2] = h2 - 1 - i - 1;
  712.  
  713.                 m_pPhysAreaInput->m_indices[6 * i + 3] = h2 - 1 - i - 1;
  714.                 m_pPhysAreaInput->m_indices[6 * i + 4] = h2 - 1 - i;
  715.                 m_pPhysAreaInput->m_indices[6 * i + 5] = i;
  716.         }
  717.  
  718.         if (keepSerializationParams)
  719.                 CopyVolatilePhysicsAreaContourSerParams(pVertices, numVertices);
  720. }
  721.  
  722. IPhysicalEntity* CWaterVolumeRenderNode::SetAndCreatePhysicsArea(const Vec3* pVertices, unsigned int numVertices)
  723. {
  724.         SetAreaPhysicsArea(pVertices, numVertices, false);
  725.  
  726.         return CreatePhysicsAreaFromSettings();
  727. }
  728.  
  729. const char* CWaterVolumeRenderNode::GetEntityClassName() const
  730. {
  731.         return "WaterVolume";
  732. }
  733.  
  734. const char* CWaterVolumeRenderNode::GetName() const
  735. {
  736.         return "WaterVolume";
  737. }
  738.  
  739. IRenderNode* CWaterVolumeRenderNode::Clone() const
  740. {
  741.         CWaterVolumeRenderNode* pWaterVol = new CWaterVolumeRenderNode();
  742.  
  743.         // CWaterVolumeRenderNode member vars
  744.         pWaterVol->m_volumeType = m_volumeType;
  745.  
  746.         pWaterVol->m_volumeID = m_volumeID;
  747.  
  748.         pWaterVol->m_volumeDepth = m_volumeDepth;
  749.         pWaterVol->m_streamSpeed = m_streamSpeed;
  750.  
  751.         pWaterVol->m_pMaterial = m_pMaterial;
  752.         pWaterVol->m_pWaterBodyIntoMat = m_pWaterBodyIntoMat;
  753.         pWaterVol->m_pWaterBodyOutofMat = m_pWaterBodyOutofMat;
  754.  
  755.         if (m_pPhysAreaInput != NULL)
  756.         {
  757.                 pWaterVol->m_pPhysAreaInput = new SWaterVolumePhysAreaInput;
  758.                 *pWaterVol->m_pPhysAreaInput = *m_pPhysAreaInput;
  759.         }
  760.         else
  761.         {
  762.                 pWaterVol->m_pPhysAreaInput = NULL;
  763.         }
  764.  
  765.         pWaterVol->m_waterSurfaceVertices = m_waterSurfaceVertices;
  766.         pWaterVol->m_waterSurfaceIndices = m_waterSurfaceIndices;
  767.  
  768.         pWaterVol->m_parentEntityWorldTM = m_parentEntityWorldTM;
  769.         pWaterVol->m_nLayerId = m_nLayerId;
  770.  
  771.         pWaterVol->m_fogDensity = m_fogDensity;
  772.         pWaterVol->m_fogColor = m_fogColor;
  773.         pWaterVol->m_fogColorAffectedBySun = m_fogColorAffectedBySun;
  774.         pWaterVol->m_fogShadowing = m_fogShadowing;
  775.  
  776.         pWaterVol->m_fogPlane = m_fogPlane;
  777.         pWaterVol->m_fogPlaneBase = m_fogPlaneBase;
  778.  
  779.         pWaterVol->m_center = m_center;
  780.         pWaterVol->m_WSBBox = m_WSBBox;
  781.  
  782.         pWaterVol->m_capFogAtVolumeDepth = m_capFogAtVolumeDepth;
  783.         pWaterVol->m_attachedToEntity = m_attachedToEntity;
  784.         pWaterVol->m_caustics = m_caustics;
  785.  
  786.         pWaterVol->m_causticIntensity = m_causticIntensity;
  787.         pWaterVol->m_causticTiling = m_causticTiling;
  788.         pWaterVol->m_causticShadow = m_causticShadow;
  789.         pWaterVol->m_causticHeight = m_causticHeight;
  790.  
  791.         // update reference to vertex and index buffer
  792.         for (int i = 0; i < RT_COMMAND_BUF_COUNT; ++i)
  793.         {
  794.                 pWaterVol->m_wvParams[i].m_pVertices = &pWaterVol->m_waterSurfaceVertices[0];
  795.                 pWaterVol->m_wvParams[i].m_numVertices = pWaterVol->m_waterSurfaceVertices.size();
  796.                 pWaterVol->m_wvParams[i].m_pIndices = &pWaterVol->m_waterSurfaceIndices[0];
  797.                 pWaterVol->m_wvParams[i].m_numIndices = pWaterVol->m_waterSurfaceIndices.size();
  798.         }
  799.  
  800.         //IRenderNode member vars
  801.         //      We cannot just copy over due to issues with the linked list of IRenderNode objects
  802.         CopyIRenderNodeData(pWaterVol);
  803.  
  804.         return pWaterVol;
  805. }
  806.  
  807. inline void TransformPosition(Vec3& pos, const Vec3& localOrigin, const Matrix34& l2w)
  808. {
  809.         pos = pos - localOrigin;
  810.         pos = l2w * pos;
  811. }
  812.  
  813. void CWaterVolumeRenderNode::Transform(const Vec3& localOrigin, const Matrix34& l2w)
  814. {
  815.         CRY_ASSERT_MESSAGE(!IsAttachedToEntity(), "FIXME: Don't currently support transforming attached water volumes");
  816.  
  817.         if (m_pPhysAreaInput != NULL)
  818.         {
  819.                 for (std::vector<Vec3>::iterator it = m_pPhysAreaInput->m_contour.begin(); it != m_pPhysAreaInput->m_contour.end(); ++it)
  820.                 {
  821.                         Vec3& pos = *it;
  822.                         TransformPosition(pos, localOrigin, l2w);
  823.                 }
  824.  
  825.                 for (std::vector<Vec3>::iterator it = m_pPhysAreaInput->m_flowContour.begin(); it != m_pPhysAreaInput->m_flowContour.end(); ++it)
  826.                 {
  827.                         Vec3& pos = *it;
  828.                         TransformPosition(pos, localOrigin, l2w);
  829.                 }
  830.         }
  831.  
  832.         for (WaterSurfaceVertices::iterator it = m_waterSurfaceVertices.begin(); it != m_waterSurfaceVertices.end(); ++it)
  833.         {
  834.                 SVF_P3F_C4B_T2F& vert = *it;
  835.                 TransformPosition(vert.xyz, localOrigin, l2w);
  836.         }
  837.  
  838.         Vec3 origFogPoint = m_fogPlane.n * m_fogPlane.d;
  839.         TransformPosition(origFogPoint, localOrigin, l2w);
  840.         m_fogPlane.SetPlane(l2w.TransformVector(m_fogPlaneBase.n).GetNormalized(), origFogPoint);
  841.  
  842.         TransformPosition(m_center, localOrigin, l2w);
  843.  
  844.         UpdateBoundingBox();
  845. }
  846.  
  847. void CWaterVolumeRenderNode::SetMatrix(const Matrix34& mat)
  848. {
  849.         if (!IsAttachedToEntity())
  850.                 return;
  851.  
  852.         m_parentEntityWorldTM = mat;
  853.         m_fogPlane.SetPlane(m_parentEntityWorldTM.TransformVector(m_fogPlaneBase.n).GetNormalized(), m_parentEntityWorldTM.GetTranslation());
  854.  
  855.         UpdateBoundingBox();
  856. }
  857.  
  858. void CWaterVolumeRenderNode::Render(const SRendParams& rParam, const SRenderingPassInfo& passInfo)
  859. {
  860.         Render_JobEntry(rParam, passInfo);
  861. }
  862.  
  863. void CWaterVolumeRenderNode::Render_JobEntry(SRendParams rParam, SRenderingPassInfo passInfo)
  864. {
  865.         FUNCTION_PROFILER_3DENGINE;
  866.  
  867.         // hack: special case for when inside amphibious vehicle
  868.         if (Get3DEngine()->GetOceanRenderFlags() & OCR_NO_DRAW)
  869.                 return;
  870.  
  871.         // anything to render?
  872.         if (passInfo.IsRecursivePass() || !m_pMaterial || !m_pWaterBodyIntoMat || !m_pWaterBodyOutofMat || !passInfo.RenderWaterVolumes() ||
  873.             m_waterSurfaceVertices.empty() || m_waterSurfaceIndices.empty())
  874.                 return;
  875.  
  876.         if (m_fogDensity == 0)
  877.                 return;
  878.  
  879.         IRenderer* pRenderer(GetRenderer());
  880.  
  881.         const int fillThreadID = passInfo.ThreadID();
  882.  
  883.         // get render objects
  884.         CRenderObject* pROVol = pRenderer->EF_GetObject_Temp(fillThreadID);
  885.         CRenderObject* pROSurf = pRenderer->EF_GetObject_Temp(fillThreadID);
  886.         if (!pROVol || !pROSurf)
  887.                 return;
  888.  
  889.         if (!m_pSurfaceRE[fillThreadID])
  890.                 return;
  891.  
  892.         float distToWaterVolumeSurface(GetCameraDistToWaterVolumeSurface(passInfo));
  893.         bool aboveWaterVolumeSurface(distToWaterVolumeSurface > 0.0f);
  894.         bool belowWaterVolume(m_capFogAtVolumeDepth && distToWaterVolumeSurface < -m_volumeDepth);
  895.         bool insideWaterVolumeSurface2D(IsCameraInsideWaterVolumeSurface2D(passInfo));
  896.         bool insideWaterVolume(insideWaterVolumeSurface2D && !aboveWaterVolumeSurface && !belowWaterVolume);
  897.  
  898.         // fill parameters to render elements
  899.         m_wvParams[fillThreadID].m_viewerInsideVolume = insideWaterVolume;
  900.         m_wvParams[fillThreadID].m_viewerCloseToWaterPlane = /*insideWaterVolumeSurface2D && */ fabsf(distToWaterVolumeSurface) < 0.5f;
  901.         m_wvParams[fillThreadID].m_viewerCloseToWaterVolume = GetCameraDistSqToWaterVolumeAABB(passInfo) < 9.0f; //Sq dist
  902.  
  903.         const float hdrMultiplier = m_fogColorAffectedBySun ? 1.0f : ((CTimeOfDay*)Get3DEngine()->GetTimeOfDay())->GetHDRMultiplier();
  904.  
  905.         m_wvParams[fillThreadID].m_fogDensity = m_fogDensity;
  906.         m_wvParams[fillThreadID].m_fogColor = m_fogColor * hdrMultiplier;
  907.         m_wvParams[fillThreadID].m_fogColorAffectedBySun = m_fogColorAffectedBySun;
  908.         m_wvParams[fillThreadID].m_fogPlane = m_fogPlane;
  909.         m_wvParams[fillThreadID].m_fogShadowing = m_fogShadowing;
  910.  
  911.         m_wvParams[fillThreadID].m_caustics = m_caustics;
  912.         m_wvParams[fillThreadID].m_causticIntensity = m_causticIntensity;
  913.         m_wvParams[fillThreadID].m_causticTiling = m_causticTiling;
  914.         m_wvParams[fillThreadID].m_causticHeight = m_causticHeight;
  915.  
  916.         m_wvParams[fillThreadID].m_center = m_center;
  917.         m_wvParams[fillThreadID].m_WSBBox = m_WSBBox;
  918.  
  919.         // if above water render fog together with water surface
  920.         bool isFastpath = GetCVars()->e_WaterVolumes == 2 && (distToWaterVolumeSurface > 0.5f || insideWaterVolume);
  921.         m_pSurfaceRE[fillThreadID]->m_drawFastPath = isFastpath;
  922.  
  923.         // submit volume
  924.         if (GetCVars()->e_Fog)
  925.         {
  926.                 if ((insideWaterVolume || (!isFastpath && aboveWaterVolumeSurface)) && m_pVolumeRE[fillThreadID])
  927.                 {
  928.                         CRY_ASSERT(!(m_pVolumeRE[fillThreadID]->m_drawWaterSurface));
  929.  
  930.                         // fill in data for render object
  931.                         if (!IsAttachedToEntity())
  932.                         {
  933.                                 pROVol->m_II.m_Matrix.SetIdentity();
  934.                         }
  935.                         else
  936.                         {
  937.                                 pROVol->m_II.m_Matrix = m_parentEntityWorldTM;
  938.                                 pROVol->m_ObjFlags |= FOB_TRANS_MASK;
  939.                         }
  940.                         pROVol->m_fSort = 0;
  941.  
  942.                         auto pMaterial = m_wvParams[fillThreadID].m_viewerInsideVolume ? m_pWaterBodyOutofMat.get() : m_pWaterBodyIntoMat.get();
  943.                         pROVol->m_pCurrMaterial = pMaterial;
  944.  
  945.                         // get shader item
  946.                         SShaderItem& shaderItem(pMaterial->GetShaderItem(0));
  947.  
  948.                         // add to renderer
  949.                         GetRenderer()->EF_AddEf(m_pVolumeRE[fillThreadID], shaderItem, pROVol, passInfo, EFSLIST_WATER_VOLUMES, aboveWaterVolumeSurface ? 0 : 1);
  950.                 }
  951.         }
  952.  
  953.         // submit surface
  954.         {
  955.                 CRY_ASSERT(m_pSurfaceRE[fillThreadID]->m_drawWaterSurface);
  956.  
  957.                 // fill in data for render object
  958.                 if (!IsAttachedToEntity())
  959.                 {
  960.                         pROSurf->m_II.m_Matrix.SetIdentity();
  961.                 }
  962.                 else
  963.                 {
  964.                         pROSurf->m_II.m_Matrix = m_parentEntityWorldTM;
  965.                         pROSurf->m_ObjFlags |= FOB_TRANS_MASK;
  966.                 }
  967.                 pROSurf->m_fSort = 0;
  968.  
  969.                 pROSurf->m_pCurrMaterial = m_pMaterial;
  970.  
  971.                 // get shader item
  972.                 SShaderItem& shaderItem(m_pMaterial->GetShaderItem(0));
  973.  
  974.                 // add to renderer
  975.                 GetRenderer()->EF_AddEf(m_pSurfaceRE[fillThreadID], shaderItem, pROSurf, passInfo, EFSLIST_WATER, 1);
  976.         }
  977. }
  978.  
  979. void CWaterVolumeRenderNode::SetMaterial(IMaterial* pMat)
  980. {
  981.         m_pMaterial = pMat;
  982. }
  983.  
  984. void CWaterVolumeRenderNode::GetMemoryUsage(ICrySizer* pSizer) const
  985. {
  986.         SIZER_COMPONENT_NAME(pSizer, "WaterVolumeNode");
  987.         pSizer->AddObject(this, sizeof(*this));
  988.         pSizer->AddObject(m_pSerParams);
  989.         pSizer->AddObject(m_pPhysAreaInput);
  990.         pSizer->AddObject(m_waterSurfaceVertices);
  991.         pSizer->AddObject(m_waterSurfaceIndices);
  992. }
  993.  
  994. void CWaterVolumeRenderNode::Precache()
  995. {
  996. }
  997.  
  998. IPhysicalEntity* CWaterVolumeRenderNode::GetPhysics() const
  999. {
  1000.         return m_pPhysArea;
  1001. }
  1002.  
  1003. void CWaterVolumeRenderNode::SetPhysics(IPhysicalEntity* pPhysArea)
  1004. {
  1005.         m_pPhysArea = pPhysArea;
  1006. }
  1007.  
  1008. void CWaterVolumeRenderNode::CheckPhysicalized()
  1009. {
  1010.         if (!GetPhysics())
  1011.                 Physicalize();
  1012. }
  1013.  
  1014. void CWaterVolumeRenderNode::Physicalize(bool bInstant)
  1015. {
  1016.         if (IsAttachedToEntity())
  1017.                 return;
  1018.  
  1019.         Dephysicalize();
  1020.  
  1021.         // setup physical area
  1022.         m_pPhysArea = CreatePhysicsAreaFromSettings();
  1023.  
  1024.         if (m_pPhysArea)
  1025.         {
  1026.                 pe_status_pos sp;
  1027.                 m_pPhysArea->GetStatus(&sp);
  1028.  
  1029.                 pe_params_buoyancy pb;
  1030.                 pb.waterPlane.n = sp.q * Vec3(0, 0, 1);
  1031.                 pb.waterPlane.origin = m_pPhysAreaInput->m_contour[0];
  1032.                 //pb.waterFlow = sp.q * Vec3( m_streamSpeed, 0, 0 );
  1033.                 m_pPhysArea->SetParams(&pb);
  1034.  
  1035.                 pe_params_foreign_data pfd;
  1036.                 pfd.pForeignData = this;
  1037.                 pfd.iForeignData = PHYS_FOREIGN_ID_WATERVOLUME;
  1038.                 pfd.iForeignFlags = 0;
  1039.                 m_pPhysArea->SetParams(&pfd);
  1040.  
  1041.                 m_pPhysArea->SetParams(&m_auxPhysParams);
  1042.         }
  1043. }
  1044.  
  1045. void CWaterVolumeRenderNode::Dephysicalize(bool bKeepIfReferenced)
  1046. {
  1047.         if (m_pPhysArea)
  1048.         {
  1049.                 GetPhysicalWorld()->DestroyPhysicalEntity(m_pPhysArea);
  1050.                 m_pPhysArea = 0;
  1051.                 m_attachedToEntity = false;
  1052.         }
  1053. }
  1054.  
  1055. float CWaterVolumeRenderNode::GetCameraDistToWaterVolumeSurface(const SRenderingPassInfo& passInfo) const
  1056. {
  1057.         const CCamera& cam(passInfo.GetCamera());
  1058.         Vec3 camPos(cam.GetPosition());
  1059.         return m_fogPlane.DistFromPlane(camPos);
  1060. }
  1061.  
  1062. float CWaterVolumeRenderNode::GetCameraDistSqToWaterVolumeAABB(const SRenderingPassInfo& passInfo) const
  1063. {
  1064.         const CCamera& cam(passInfo.GetCamera());
  1065.         Vec3 camPos(cam.GetPosition());
  1066.         return m_WSBBox.GetDistanceSqr(camPos);
  1067. }
  1068.  
  1069. bool CWaterVolumeRenderNode::IsCameraInsideWaterVolumeSurface2D(const SRenderingPassInfo& passInfo) const
  1070. {
  1071.         const CCamera& cam(passInfo.GetCamera());
  1072.         Vec3 camPos(cam.GetPosition());
  1073.  
  1074.         pe_status_area sa;
  1075.         sa.bUniformOnly = true;
  1076.         MARK_UNUSED sa.ctr;
  1077.         if (m_pPhysArea && m_pPhysArea->GetStatus(&sa) && sa.pSurface)
  1078.         {
  1079.                 pe_status_contains_point scp;
  1080.                 scp.pt = camPos;
  1081.                 return m_pPhysArea->GetStatus(&scp) != 0;
  1082.         }
  1083.  
  1084.         WaterVolumeRenderNodeUtils::VertexAccess<SVF_P3F_C4B_T2F> ca(&m_waterSurfaceVertices[0], m_waterSurfaceVertices.size());
  1085.         for (size_t i(0); i < m_waterSurfaceIndices.size(); i += 3)
  1086.         {
  1087.                 const Vec3 v0 = m_parentEntityWorldTM.TransformPoint(ca[m_waterSurfaceIndices[i]]);
  1088.                 const Vec3 v1 = m_parentEntityWorldTM.TransformPoint(ca[m_waterSurfaceIndices[i + 1]]);
  1089.                 const Vec3 v2 = m_parentEntityWorldTM.TransformPoint(ca[m_waterSurfaceIndices[i + 2]]);
  1090.  
  1091.                 if (WaterVolumeRenderNodeUtils::InsideTriangle(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y, camPos.x, camPos.y))
  1092.                         return true;
  1093.         }
  1094.  
  1095.         return false;
  1096. }
  1097.  
  1098. void CWaterVolumeRenderNode::UpdateBoundingBox()
  1099. {
  1100.         m_WSBBox.Reset();
  1101.         for (size_t i(0); i < m_waterSurfaceVertices.size(); ++i)
  1102.                 m_WSBBox.Add(m_parentEntityWorldTM.TransformPoint(m_waterSurfaceVertices[i].xyz));
  1103.  
  1104.         if (IVisArea* pArea = Get3DEngine()->GetVisAreaFromPos(m_WSBBox.GetCenter()))
  1105.         {
  1106.                 if (m_WSBBox.min.z > pArea->GetAABBox()->min.z)
  1107.                         m_WSBBox.min.z = pArea->GetAABBox()->min.z;
  1108.                 return;
  1109.         }
  1110.  
  1111.         m_WSBBox.min.z -= m_volumeDepth;
  1112.         m_center = m_WSBBox.GetCenter();
  1113. }
  1114.  
  1115. const SWaterVolumeSerialize* CWaterVolumeRenderNode::GetSerializationParams()
  1116. {
  1117.         if (!m_pSerParams)
  1118.                 return 0;
  1119.  
  1120.         // before returning, copy non-volatile serialization params
  1121.         m_pSerParams->m_volumeType = m_volumeType;
  1122.         m_pSerParams->m_volumeID = m_volumeID;
  1123.  
  1124.         m_pSerParams->m_pMaterial = m_pMaterial;
  1125.  
  1126.         m_pSerParams->m_fogDensity = m_fogDensity;
  1127.         m_pSerParams->m_fogColor = m_fogColor;
  1128.         m_pSerParams->m_fogColorAffectedBySun = m_fogColorAffectedBySun;
  1129.         m_pSerParams->m_fogPlane = m_fogPlane;
  1130.         m_pSerParams->m_fogShadowing = m_fogShadowing;
  1131.  
  1132.         m_pSerParams->m_volumeDepth = m_volumeDepth;
  1133.         m_pSerParams->m_streamSpeed = m_streamSpeed;
  1134.         m_pSerParams->m_capFogAtVolumeDepth = m_capFogAtVolumeDepth;
  1135.  
  1136.         m_pSerParams->m_caustics = m_caustics;
  1137.         m_pSerParams->m_causticIntensity = m_causticIntensity;
  1138.         m_pSerParams->m_causticTiling = m_causticTiling;
  1139.         m_pSerParams->m_causticHeight = m_causticHeight;
  1140.  
  1141.         return m_pSerParams;
  1142. }
  1143.  
  1144. void CWaterVolumeRenderNode::CopyVolatilePhysicsAreaContourSerParams(const Vec3* pVertices, unsigned int numVertices)
  1145. {
  1146.         if (!m_pSerParams)
  1147.                 m_pSerParams = new SWaterVolumeSerialize;
  1148.  
  1149.         m_pSerParams->m_physicsAreaContour.resize(numVertices);
  1150.         for (unsigned int i(0); i < numVertices; ++i)
  1151.                 m_pSerParams->m_physicsAreaContour[i] = pVertices[i];
  1152. }
  1153.  
  1154. void CWaterVolumeRenderNode::CopyVolatileRiverSerParams(const Vec3* pVertices, unsigned int numVertices, float uTexCoordBegin, float uTexCoordEnd, const Vec2& surfUVScale)
  1155. {
  1156.         if (!m_pSerParams)
  1157.                 m_pSerParams = new SWaterVolumeSerialize;
  1158.  
  1159.         m_pSerParams->m_uTexCoordBegin = uTexCoordBegin;
  1160.         m_pSerParams->m_uTexCoordEnd = uTexCoordEnd;
  1161.  
  1162.         m_pSerParams->m_surfUScale = surfUVScale.x;
  1163.         m_pSerParams->m_surfVScale = surfUVScale.y;
  1164.  
  1165.         m_pSerParams->m_vertices.resize(numVertices);
  1166.         for (uint32 i(0); i < numVertices; ++i)
  1167.                 m_pSerParams->m_vertices[i] = pVertices[i];
  1168. }
  1169.  
  1170. void CWaterVolumeRenderNode::CopyVolatileAreaSerParams(const Vec3* pVertices, unsigned int numVertices, const Vec2& surfUVScale)
  1171. {
  1172.         if (!m_pSerParams)
  1173.                 m_pSerParams = new SWaterVolumeSerialize;
  1174.  
  1175.         m_pSerParams->m_uTexCoordBegin = 1.0f;
  1176.         m_pSerParams->m_uTexCoordEnd = 1.0f;
  1177.  
  1178.         m_pSerParams->m_surfUScale = surfUVScale.x;
  1179.         m_pSerParams->m_surfVScale = surfUVScale.y;
  1180.  
  1181.         m_pSerParams->m_vertices.resize(numVertices);
  1182.         for (uint32 i(0); i < numVertices; ++i)
  1183.                 m_pSerParams->m_vertices[i] = pVertices[i];
  1184. }
  1185.  
  1186. int OnWaterUpdate(const EventPhysAreaChange* pEvent)
  1187. {
  1188.         if (pEvent->iForeignData == PHYS_FOREIGN_ID_WATERVOLUME)
  1189.         {
  1190.                 CWaterVolumeRenderNode* pWVRN = (CWaterVolumeRenderNode*)pEvent->pForeignData;
  1191.                 pe_status_area sa;
  1192.                 sa.bUniformOnly = true;
  1193.                 MARK_UNUSED sa.ctr;
  1194.                 if (pWVRN->GetPhysics() != pEvent->pEntity || !pEvent->pEntity->GetStatus(&sa))
  1195.                         return 1;
  1196.                 if (pEvent->pContainer)
  1197.                 {
  1198.                         pWVRN->SetAreaAttachedToEntity();
  1199.                         pWVRN->SetMatrix(Matrix34(Vec3(1), pEvent->qContainer, pEvent->posContainer));
  1200.                 }
  1201.                 pWVRN->SyncToPhysMesh(QuatT(pEvent->q, pEvent->pos), sa.pSurface, pEvent->depth);
  1202.         }
  1203.         return 1;
  1204. }
  1205.  
  1206. IPhysicalEntity* CWaterVolumeRenderNode::CreatePhysicsAreaFromSettings()
  1207. {
  1208.         if (!m_pPhysAreaInput)
  1209.                 return NULL;
  1210.  
  1211.         Vec3* pFlow(!m_pPhysAreaInput->m_flowContour.empty() ? &m_pPhysAreaInput->m_flowContour[0] : 0);
  1212.         //assert( m_pPhysAreaInput->m_contour.size() >= 3 && ( !pFlow || m_pPhysAreaInput->m_contour.size() == m_pPhysAreaInput->m_flowContour.size() ) && m_pPhysAreaInput->m_indices.size() >= 3 && m_pPhysAreaInput->m_indices.size() % 3 == 0 );
  1213.         if (m_pPhysAreaInput->m_contour.size() < 3 || (pFlow && m_pPhysAreaInput->m_contour.size() != m_pPhysAreaInput->m_flowContour.size()) || m_pPhysAreaInput->m_indices.size() < 3 || m_pPhysAreaInput->m_indices.size() % 3 != 0)
  1214.                 return NULL;
  1215.  
  1216.         GetPhysicalWorld()->AddEventClient(EventPhysAreaChange::id, (int (*)(const EventPhys*))OnWaterUpdate, 1);
  1217.  
  1218.         // setup physical area
  1219.         return GetPhysicalWorld()->AddArea(&m_pPhysAreaInput->m_contour[0], m_pPhysAreaInput->m_contour.size(), min(0.0f, -m_volumeDepth), 10.0f,
  1220.                                            Vec3(ZERO), Quat(IDENTITY), 1.0f, Vec3(ZERO), &m_pPhysAreaInput->m_indices[0], m_pPhysAreaInput->m_indices.size() / 3, pFlow);
  1221. }
  1222.  
  1223. void CWaterVolumeRenderNode::SyncToPhysMesh(const QuatT& qtSurface, IGeometry* pSurface, float depth)
  1224. {
  1225.         mesh_data* pmd;
  1226.         if (!pSurface || pSurface->GetType() != GEOM_TRIMESH || !(pmd = (mesh_data*)pSurface->GetData()))
  1227.                 return;
  1228.         bool bResized = false;
  1229.         if (bResized = m_waterSurfaceVertices.size() != pmd->nVertices)
  1230.                 m_waterSurfaceVertices.resize(pmd->nVertices);
  1231.         Vec2 uvScale = m_pSerParams ? Vec2(m_pSerParams->m_surfUScale, m_pSerParams->m_surfVScale) : Vec2(1.0f, 1.0f);
  1232.         for (int i = 0; i < pmd->nVertices; i++)
  1233.         {
  1234.                 m_waterSurfaceVertices[i].xyz = qtSurface * pmd->pVertices[i];
  1235.                 m_waterSurfaceVertices[i].st = Vec2(pmd->pVertices[i].x * uvScale.x, pmd->pVertices[i].y * uvScale.y);
  1236.         }
  1237.         if (m_waterSurfaceIndices.size() != pmd->nTris * 3)
  1238.                 m_waterSurfaceIndices.resize(pmd->nTris * 3), bResized = true;
  1239.         for (int i = 0; i < pmd->nTris * 3; i++)
  1240.                 m_waterSurfaceIndices[i] = pmd->pIndices[i];
  1241.  
  1242.         if (bResized)
  1243.                 for (int i = 0; i < RT_COMMAND_BUF_COUNT; ++i)
  1244.                 {
  1245.                         m_wvParams[i].m_pVertices = &m_waterSurfaceVertices[0];
  1246.                         m_wvParams[i].m_numVertices = m_waterSurfaceVertices.size();
  1247.                         m_wvParams[i].m_pIndices = &m_waterSurfaceIndices[0];
  1248.                         m_wvParams[i].m_numIndices = m_waterSurfaceIndices.size();
  1249.                 }
  1250.  
  1251.         m_fogPlane.SetPlane(qtSurface.q * Vec3(0, 0, 1), qtSurface.t);
  1252.         m_volumeDepth = depth;
  1253.         UpdateBoundingBox();
  1254. }
  1255.  
  1256. void CWaterVolumeRenderNode::OffsetPosition(const Vec3& delta)
  1257. {
  1258.         if (m_pTempData) m_pTempData->OffsetPosition(delta);
  1259.         m_vOffset += delta;
  1260.         m_center += delta;
  1261.         m_WSBBox.Move(delta);
  1262.         for (int i = 0; i < (int)m_waterSurfaceVertices.size(); ++i)
  1263.                 m_waterSurfaceVertices[i].xyz += delta;
  1264.  
  1265.         if (m_pPhysAreaInput)
  1266.         {
  1267.                 for (std::vector<Vec3>::iterator it = m_pPhysAreaInput->m_contour.begin(); it != m_pPhysAreaInput->m_contour.end(); ++it)
  1268.                         *it += delta;
  1269.                 for (std::vector<Vec3>::iterator it = m_pPhysAreaInput->m_flowContour.begin(); it != m_pPhysAreaInput->m_flowContour.end(); ++it)
  1270.                         *it += delta;
  1271.         }
  1272.  
  1273.         if (m_pPhysArea)
  1274.         {
  1275.                 pe_params_pos par_pos;
  1276.                 m_pPhysArea->GetParams(&par_pos);
  1277.                 par_pos.bRecalcBounds |= 2;
  1278.                 par_pos.pos = m_vOffset;
  1279.                 m_pPhysArea->SetParams(&par_pos);
  1280.         }
  1281. }
  1282.  
  1283. void CWaterVolumeRenderNode::FillBBox(AABB& aabb)
  1284. {
  1285.         aabb = CWaterVolumeRenderNode::GetBBox();
  1286. }
  1287.  
  1288. EERType CWaterVolumeRenderNode::GetRenderNodeType()
  1289. {
  1290.         return eERType_WaterVolume;
  1291. }
  1292.  
  1293. float CWaterVolumeRenderNode::GetMaxViewDist()
  1294. {
  1295.         if (GetMinSpecFromRenderNodeFlags(m_dwRndFlags) == CONFIG_DETAIL_SPEC)
  1296.                 return max(GetCVars()->e_ViewDistMin, CWaterVolumeRenderNode::GetBBox().GetRadius() * GetCVars()->e_ViewDistRatioDetail * GetViewDistRatioNormilized());
  1297.  
  1298.         return max(GetCVars()->e_ViewDistMin, CWaterVolumeRenderNode::GetBBox().GetRadius() * GetCVars()->e_ViewDistRatio * GetViewDistRatioNormilized());
  1299. }
  1300.  
  1301. Vec3 CWaterVolumeRenderNode::GetPos(bool bWorldOnly) const
  1302. {
  1303.         return m_center;
  1304. }
  1305.  
  1306. IMaterial* CWaterVolumeRenderNode::GetMaterial(Vec3* pHitPos) const
  1307. {
  1308.         return m_pMaterial;
  1309. }
  1310.  
downloadWaterVolumeRenderNode.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