BVB Source Codes

CRYENGINE Show RopeRenderNode.cpp Source code

Return Download CRYENGINE: download RopeRenderNode.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 "RopeRenderNode.h"
  5. #include "VisAreas.h"
  6. #include "ObjMan.h"
  7. #include "MatMan.h"
  8.  
  9. #include <CryAudio/IAudioSystem.h>
  10.  
  11. #pragma warning(disable: 4244)
  12.  
  13. class TubeSurface : public _i_reference_target_t
  14. {
  15.  
  16. public:
  17.         Matrix34 m_worldTM;
  18.  
  19.         // If rkUpVector is not the zero vector, it will be used as 'up' in the frame calculations.  If it is the zero
  20.         // vector, the Frenet frame will be used.  If bWantColors is 'true',
  21.         // the vertex colors are allocated and set to black.  The application
  22.         // needs to assign colors as needed.  If either of pkTextureMin or
  23.         // pkTextureMax is not null, both must be not null.  In this case,
  24.         // texture coordinates are generated for the surface.
  25.         void GenerateSurface(spline::CatmullRomSpline<Vec3>* pSpline, float fRadius, bool bClosed,
  26.                              const Vec3& rkUpVector, int iMedialSamples, int iSliceSamples,
  27.                              bool bWantNormals, bool bWantColors, bool bSampleByArcLength,
  28.                              bool bInsideView, const Vec2* pkTextureMin, const Vec2* pkTextureMax);
  29.  
  30.         TubeSurface();
  31.         ~TubeSurface();
  32.  
  33.         // member access
  34.         Vec3&       UpVector();
  35.         const Vec3& GetUpVector() const;
  36.         int         GetSliceSamples() const;
  37.  
  38.         // Generate vertices for the end slices.  These are useful when you build
  39.         // an open tube and want to attach meshes at the ends to close the tube.
  40.         // The input array must have size (at least) S+1 where S is the number
  41.         // returned by GetSliceSamples.  Function GetTMinSlice is used to access
  42.         // the slice corresponding to the medial curve evaluated at its domain
  43.         // minimum, tmin.  Function GetTMaxSlice accesses the slice for the
  44.         // domain maximum, tmax.  If the curve is closed, the slices are the same.
  45.         void GetTMinSlice(Vec3* akSlice);
  46.         void GetTMaxSlice(Vec3* akSlice);
  47.  
  48.         // If the medial curve is modified, for example if it is control point
  49.         // based and the control points are modified, then you should call this
  50.         // update function to recompute the tube surface geometry.
  51.         void UpdateSurface();
  52.  
  53.         //////////////////////////////////////////////////////////////////////////
  54.         // tessellation support
  55.         int  Index(int iS, int iM) { return iS + (m_iSliceSamples + 1) * iM; };
  56.         void ComputeSinCos();
  57.         void ComputeVertices(Vec3* akVertex);
  58.         void ComputeNormals();
  59.         void ComputeTextures(const Vec2& rkTextureMin,
  60.                              const Vec2& rkTextureMax, Vec2* akTexture);
  61.         void ComputeConnectivity(int& riTQuantity, vtx_idx*& raiConnect, bool bInsideView);
  62.  
  63.         float                           m_fRadius;
  64.         int                             m_iMedialSamples, m_iSliceSamples;
  65.         Vec3                            m_kUpVector;
  66.         float*                          m_afSin;
  67.         float*                          m_afCos;
  68.         bool                            m_bClosed, m_bSampleByArcLength;
  69.         bool                            m_bCap;
  70.  
  71.         int                             nAllocVerts;
  72.         int                             nAllocIndices;
  73.         int                             nAllocSinCos;
  74.  
  75.         int                             iVQuantity;
  76.         int                             iNumIndices;
  77.  
  78.         int                             iTQuantity; // Num triangles (use iNumIndices instead).
  79.  
  80.         Vec3*                           m_akTangents;
  81.         Vec3*                           m_akBitangents;
  82.  
  83.         Vec3*                           m_akVertex;
  84.         Vec3*                           m_akNormals;
  85.         Vec2*                           m_akTexture;
  86.         vtx_idx*                        m_pIndices;
  87.         spline::CatmullRomSpline<Vec3>* m_pSpline;
  88. };
  89.  
  90. //////////////////////////////////////////////////////////////////////////
  91. TubeSurface::TubeSurface()
  92. {
  93.         m_afSin = NULL;
  94.         m_afCos = NULL;
  95.  
  96.         m_bCap = false;
  97.         m_bClosed = false;
  98.         m_bSampleByArcLength = false;
  99.         m_fRadius = 0;
  100.         m_iMedialSamples = 0;
  101.         m_iSliceSamples = 0;
  102.  
  103.         nAllocVerts = 0;
  104.         nAllocIndices = 0;
  105.         nAllocSinCos = 0;
  106.  
  107.         iVQuantity = 0;
  108.         iTQuantity = 0;
  109.         iNumIndices = 0;
  110.  
  111.         m_pSpline = NULL;
  112.         m_akTangents = NULL;
  113.         m_akBitangents = NULL;
  114.  
  115.         m_akVertex = NULL;
  116.         m_akNormals = NULL;
  117.         m_akTexture = NULL;
  118.         m_pIndices = NULL;
  119. }
  120.  
  121. //----------------------------------------------------------------------------
  122. void TubeSurface::GenerateSurface(spline::CatmullRomSpline<Vec3>* pSpline, float fRadius,
  123.                                   bool bClosed, const Vec3& rkUpVector, int iMedialSamples,
  124.                                   int iSliceSamples, bool bWantNormals, bool bWantColors,
  125.                                   bool bSampleByArcLength, bool bInsideView, const Vec2* pkTextureMin, const Vec2* pkTextureMax)
  126. {
  127.         assert((pkTextureMin && pkTextureMax) || (!pkTextureMin && !pkTextureMax));
  128.  
  129.         m_pSpline = pSpline;
  130.         m_fRadius = fRadius;
  131.         m_kUpVector = rkUpVector;
  132.         m_iMedialSamples = iMedialSamples;
  133.         m_iSliceSamples = iSliceSamples;
  134.         m_bClosed = bClosed;
  135.         m_bSampleByArcLength = bSampleByArcLength;
  136.  
  137.         m_bCap = !m_bClosed;
  138.         // compute the surface vertices
  139.         if (m_bClosed)
  140.                 iVQuantity = (m_iSliceSamples + 1) * (m_iMedialSamples + 1);
  141.         else
  142.                 iVQuantity = (m_iSliceSamples + 1) * m_iMedialSamples;
  143.  
  144.         bool bAllocVerts = false;
  145.         if (iVQuantity > nAllocVerts || !m_akVertex)
  146.         {
  147.                 bAllocVerts = true;
  148.                 nAllocVerts = iVQuantity;
  149.  
  150.                 delete[] m_akVertex;
  151.                 m_akVertex = new Vec3[nAllocVerts];
  152.         }
  153.  
  154.         ComputeSinCos();
  155.         ComputeVertices(m_akVertex);
  156.  
  157.         // compute the surface normals
  158.         if (bWantNormals)
  159.         {
  160.                 if (bAllocVerts)
  161.                 {
  162.                         delete[] m_akNormals;
  163.                         delete[] m_akTangents;
  164.                         delete[] m_akBitangents;
  165.  
  166.                         m_akNormals = new Vec3[iVQuantity];
  167.                         m_akTangents = new Vec3[iVQuantity];
  168.                         m_akBitangents = new Vec3[iVQuantity];
  169.                 }
  170.                 ComputeNormals();
  171.         }
  172.  
  173.         // compute the surface textures coordinates
  174.         if (pkTextureMin && pkTextureMax)
  175.         {
  176.                 if (bAllocVerts)
  177.                 {
  178.                         delete[] m_akTexture;
  179.                         m_akTexture = new Vec2[iVQuantity];
  180.                 }
  181.  
  182.                 ComputeTextures(*pkTextureMin, *pkTextureMax, m_akTexture);
  183.         }
  184.  
  185.         // compute the surface triangle connectivity
  186.         ComputeConnectivity(iTQuantity, m_pIndices, bInsideView);
  187.  
  188.         // create the triangle mesh for the tube surface
  189.         //Reconstruct(iVQuantity,akVertex,akNormal,akColor,akTexture,iTQuantity,aiConnect);
  190. }
  191.  
  192. //----------------------------------------------------------------------------
  193. TubeSurface::~TubeSurface()
  194. {
  195.         delete[] m_pIndices;
  196.         delete[] m_akTexture;
  197.         delete[] m_akBitangents;
  198.         delete[] m_akTangents;
  199.         delete[] m_akNormals;
  200.         delete[] m_akVertex;
  201.         delete[] m_afSin;
  202.         delete[] m_afCos;
  203. }
  204. //----------------------------------------------------------------------------
  205. void TubeSurface::ComputeSinCos()
  206. {
  207.         // Compute slice vertex coefficients.  The first and last coefficients
  208.         // are duplicated to allow a closed cross section that has two different
  209.         // pairs of texture coordinates at the shared vertex.
  210.  
  211.         if (m_iSliceSamples + 1 != nAllocSinCos)
  212.         {
  213.                 nAllocSinCos = m_iSliceSamples + 1;
  214.                 delete[]m_afSin;
  215.                 delete[]m_afCos;
  216.                 m_afSin = new float[nAllocSinCos];
  217.                 m_afCos = new float[nAllocSinCos];
  218.         }
  219.  
  220.         PREFAST_ASSUME(m_iSliceSamples > 0 && m_iSliceSamples == nAllocSinCos - 1);
  221.  
  222.         float fInvSliceSamples = 1.0f / (float)m_iSliceSamples;
  223.         for (int i = 0; i < m_iSliceSamples; i++)
  224.         {
  225.                 float fAngle = gf_PI2 * fInvSliceSamples * i;
  226.                 m_afCos[i] = cosf(fAngle);
  227.                 m_afSin[i] = sinf(fAngle);
  228.         }
  229.         m_afSin[m_iSliceSamples] = m_afSin[0];
  230.         m_afCos[m_iSliceSamples] = m_afCos[0];
  231. }
  232. //----------------------------------------------------------------------------
  233. void TubeSurface::ComputeVertices(Vec3* akVertex)
  234. {
  235.         float fTMin = m_pSpline->GetRangeStart();
  236.         float fTRange = m_pSpline->GetRangeEnd() - fTMin;
  237.  
  238.         // sampling by arc length requires the total length of the curve
  239.         /*      float fTotalLength;
  240.            if ( m_bSampleByArcLength )
  241.             //fTotalLength = m_pkMedial->GetTotalLength();
  242.             fTotalLength = 0.0f;
  243.            else
  244.             fTotalLength = 0.0f;
  245.          */
  246.         if (Cry3DEngineBase::GetCVars()->e_Ropes == 2)
  247.         {
  248.                 for (int i = 0, npoints = m_pSpline->num_keys() - 1; i < npoints; i++)
  249.                 {
  250.                         gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(m_worldTM * m_pSpline->value(i), ColorB(0, 255, 0, 255), m_worldTM * m_pSpline->value(i + 1), ColorB(0, 255, 0, 255), 6);
  251.                 }
  252.         }
  253.  
  254.         // vertex construction requires a normalized time (uses a division)
  255.         float fDenom;
  256.         if (m_bClosed)
  257.                 fDenom = 1.0f / (float)m_iMedialSamples;
  258.         else
  259.                 fDenom = 1.0f / (float)(m_iMedialSamples - 1);
  260.  
  261.         Vec3 kT_Prev = Vec3(1.0f, 0, 0), kB = m_kUpVector;
  262.         for (int iM = 0, iV = 0; iM < m_iMedialSamples; iM++)
  263.         {
  264.                 float fT = fTMin + iM * fTRange * fDenom;
  265.  
  266.                 float fRadius = m_fRadius;
  267.  
  268.                 // compute frame (position P, tangent T, normal N, bitangent B)
  269.                 Vec3 kP, kP1, kT, kN;
  270.  
  271.                 {
  272.                         // Always use 'up' vector N rather than curve normal.  You must
  273.                         // constrain the curve so that T and N are never parallel.  To
  274.                         // build the frame from this, let
  275.                         //     B = Cross(T,N)/Length(Cross(T,N))
  276.                         // and replace
  277.                         //     N = Cross(B,T)/Length(Cross(B,T)).
  278.  
  279.                         //kP = m_pkMedial->GetPosition(fT);
  280.                         //kT = m_pkMedial->GetTangent(fT);
  281.                         if (iM < m_iMedialSamples - 1)
  282.                         {
  283.                                 m_pSpline->interpolate(fT, kP);
  284.                                 m_pSpline->interpolate(fT + 0.01f, kP1);
  285.                                 kT = (kP1 - kP);
  286.                         }
  287.                         else
  288.                         {
  289.                                 m_pSpline->interpolate(fT - 0.01f, kP1);
  290.                                 m_pSpline->interpolate(fT, kP);
  291.                                 kT = (kP - kP1);
  292.                         }
  293.  
  294.                         if (!kT.IsZero())
  295.                                 kT.NormalizeFast();
  296.                         else
  297.                         {
  298.                                 // Take direction of last points.
  299.                                 kT = kT_Prev;
  300.                         }
  301.                         kT_Prev = kT;
  302.                         //kT = m_pkMedial->GetTangent(fT);
  303.  
  304.                         kB -= kT * (kB * kT);
  305.                         if (kB.len2() < sqr(0.001f))
  306.                                 kB = kT.GetOrthogonal();
  307.                         //kB = kT.Cross(m_kUpVector);
  308.                         //if (kB.IsZero())
  309.                         //      kB = Vec3(1.0f,0,0);
  310.                         kB.NormalizeFast();
  311.                         kN = kB.Cross(kT);
  312.                         kN.NormalizeFast();
  313.                 }
  314.  
  315.                 // compute slice vertices, duplication at end point as noted earlier
  316.                 int iSave = iV;
  317.                 for (int i = 0; i < m_iSliceSamples; i++)
  318.                 {
  319.                         akVertex[iV] = kP + fRadius * (m_afCos[i] * kN + m_afSin[i] * kB);
  320.  
  321.                         if (Cry3DEngineBase::GetCVars()->e_Ropes == 2)
  322.                         {
  323.                                 ColorB col = ColorB(255, 0, 0, 255);
  324.                                 if (i == 0)
  325.                                         col = ColorB(255, 0, 0, 255);
  326.                                 else if (i == 1)
  327.                                         col = ColorB(0, 255, 0, 255);
  328.                                 else
  329.                                         col = ColorB(0, 0, 255, 255);
  330.                                 gEnv->pRenderer->GetIRenderAuxGeom()->DrawPoint(m_worldTM * akVertex[iV], col, 8);
  331.                         }
  332.  
  333.                         iV++;
  334.                 }
  335.                 akVertex[iV] = akVertex[iSave];
  336.                 iV++;
  337.         }
  338.  
  339.         if (m_bClosed)
  340.         {
  341.                 for (int i = 0; i <= m_iSliceSamples; i++)
  342.                 {
  343.                         int i1 = Index(i, m_iMedialSamples);
  344.                         int i0 = Index(i, 0);
  345.                         akVertex[i1] = akVertex[i0];
  346.                 }
  347.         }
  348. }
  349. //----------------------------------------------------------------------------
  350. void TubeSurface::ComputeNormals()
  351. {
  352.         int iS, iSm, iSp, iM, iMm, iMp;
  353.         Vec3 kDir0, kDir1;
  354.  
  355.         // interior normals (central differences)
  356.         for (iM = 1; iM <= m_iMedialSamples - 2; iM++)
  357.         {
  358.                 for (iS = 0; iS < m_iSliceSamples; iS++)
  359.                 {
  360.                         iSm = (iS > 0 ? iS - 1 : m_iSliceSamples - 1);
  361.                         iSp = iS + 1;
  362.                         iMm = iM - 1;
  363.                         iMp = iM + 1;
  364.  
  365.                         kDir0 = m_akVertex[Index(iSm, iM)] - m_akVertex[Index(iSp, iM)];
  366.                         kDir1 = m_akVertex[Index(iS, iMm)] - m_akVertex[Index(iS, iMp)];
  367.  
  368.                         if (kDir0.IsZero(1e-10f))
  369.                                 kDir0 = Vec3(1, 0, 0);
  370.                         if (kDir1.IsZero(1e-10f))
  371.                                 kDir1 = Vec3(0, 1, 0);
  372.  
  373.                         Vec3 kN = kDir0.Cross(kDir1); // Normal
  374.                         Vec3 kT = kDir0;              // Tangent
  375.                         Vec3 kB = kDir1;              // Bitangent
  376.  
  377.                         if (kN.IsZero(1e-10f))
  378.                                 kN = Vec3(0, 0, 1);
  379.  
  380.                         kN.NormalizeFast();
  381.                         kT.NormalizeFast();
  382.                         kB.NormalizeFast();
  383.  
  384.                         int nIndex = Index(iS, iM);
  385.                         m_akNormals[nIndex] = kN;
  386.                         m_akTangents[nIndex] = kT;
  387.                         m_akBitangents[nIndex] = kB;
  388.                 }
  389.  
  390.                 m_akNormals[Index(m_iSliceSamples, iM)] = m_akNormals[Index(0, iM)];
  391.                 m_akTangents[Index(m_iSliceSamples, iM)] = m_akTangents[Index(0, iM)];
  392.                 m_akBitangents[Index(m_iSliceSamples, iM)] = m_akBitangents[Index(0, iM)];
  393.         }
  394.  
  395.         // boundary normals
  396.         if (m_bClosed)
  397.         {
  398.                 // central differences
  399.                 for (iS = 0; iS < m_iSliceSamples; iS++)
  400.                 {
  401.                         iSm = (iS > 0 ? iS - 1 : m_iSliceSamples - 1);
  402.                         iSp = iS + 1;
  403.  
  404.                         // m = 0
  405.                         kDir0 = m_akVertex[Index(iSm, 0)] - m_akVertex[Index(iSp, 0)];
  406.                         kDir1 = m_akVertex[Index(iS, m_iMedialSamples - 1)] - m_akVertex[Index(iS, 1)];
  407.                         m_akNormals[iS] = kDir0.Cross(kDir1).GetNormalized();
  408.  
  409.                         // m = max
  410.                         m_akNormals[Index(iS, m_iMedialSamples)] = m_akNormals[Index(iS, 0)];
  411.                 }
  412.                 m_akNormals[Index(m_iSliceSamples, 0)] = m_akNormals[Index(0, 0)];
  413.                 m_akNormals[Index(m_iSliceSamples, m_iMedialSamples)] = m_akNormals[Index(0, m_iMedialSamples)];
  414.         }
  415.         else
  416.         {
  417.                 // one-sided finite differences
  418.  
  419.                 // m = 0
  420.                 for (iS = 0; iS < m_iSliceSamples; iS++)
  421.                 {
  422.                         iSm = (iS > 0 ? iS - 1 : m_iSliceSamples - 1);
  423.                         iSp = iS + 1;
  424.  
  425.                         kDir0 = m_akVertex[Index(iSm, 0)] - m_akVertex[Index(iSp, 0)];
  426.                         kDir1 = m_akVertex[Index(iS, 0)] - m_akVertex[Index(iS, 1)];
  427.                         //m_akNormals[Index(iS,0)] = kDir0.Cross(kDir1).GetNormalized();
  428.  
  429.                         if (kDir0.IsZero())
  430.                                 kDir0 = Vec3(1, 0, 0);
  431.                         if (kDir1.IsZero())
  432.                                 kDir1 = Vec3(0, 1, 0);
  433.  
  434.                         Vec3 kN = kDir0.Cross(kDir1); // Normal
  435.                         Vec3 kT = kDir0;              // Tangent
  436.                         Vec3 kB = kDir1;              // Bitangent
  437.  
  438.                         if (kN.IsZero(1e-10f))
  439.                                 kN = Vec3(0, 0, 1);
  440.  
  441.                         kN.NormalizeFast();
  442.                         kT.NormalizeFast();
  443.                         kB.NormalizeFast();
  444.  
  445.                         int nIndex = iS;
  446.                         m_akNormals[nIndex] = kN;
  447.                         m_akTangents[nIndex] = kT;
  448.                         m_akBitangents[nIndex] = kB;
  449.                 }
  450.                 m_akNormals[Index(m_iSliceSamples, 0)] = m_akNormals[Index(0, 0)];
  451.                 m_akTangents[Index(m_iSliceSamples, 0)] = m_akTangents[Index(0, 0)];
  452.                 m_akBitangents[Index(m_iSliceSamples, 0)] = m_akBitangents[Index(0, 0)];
  453.  
  454.                 // m = max-1
  455.                 for (iS = 0; iS < m_iSliceSamples; iS++)
  456.                 {
  457.                         iSm = (iS > 0 ? iS - 1 : m_iSliceSamples - 1);
  458.                         iSp = iS + 1;
  459.                         kDir0 = m_akVertex[Index(iSm, m_iMedialSamples - 1)] - m_akVertex[Index(iSp, m_iMedialSamples - 1)];
  460.                         kDir1 = m_akVertex[Index(iS, m_iMedialSamples - 2)] - m_akVertex[Index(iS, m_iMedialSamples - 1)];
  461.                         //m_akNormals[iS] = kDir0.Cross(kDir1).GetNormalized();
  462.  
  463.                         if (kDir0.IsZero())
  464.                                 kDir0 = Vec3(1, 0, 0);
  465.                         if (kDir1.IsZero())
  466.                                 kDir1 = Vec3(0, 1, 0);
  467.  
  468.                         Vec3 kN = kDir0.Cross(kDir1); // Normal
  469.                         Vec3 kT = kDir0;              // Tangent
  470.                         Vec3 kB = kDir1;              // Bitangent
  471.  
  472.                         if (kN.IsZero(1e-10f))
  473.                                 kN = Vec3(0, 0, 1);
  474.  
  475.                         kN.NormalizeFast();
  476.                         kT.NormalizeFast();
  477.                         kB.NormalizeFast();
  478.  
  479.                         int nIndex = Index(iS, m_iMedialSamples - 1);
  480.                         m_akNormals[nIndex] = kN;
  481.                         m_akTangents[nIndex] = kT;
  482.                         m_akBitangents[nIndex] = kB;
  483.                 }
  484.                 m_akNormals[Index(m_iSliceSamples, m_iMedialSamples - 1)] = m_akNormals[Index(0, m_iMedialSamples - 1)];
  485.                 m_akTangents[Index(m_iSliceSamples, m_iMedialSamples - 1)] = m_akTangents[Index(0, m_iMedialSamples - 1)];
  486.                 m_akBitangents[Index(m_iSliceSamples, m_iMedialSamples - 1)] = m_akBitangents[Index(0, m_iMedialSamples - 1)];
  487.         }
  488. }
  489.  
  490. //----------------------------------------------------------------------------
  491. void TubeSurface::ComputeTextures(const Vec2& rkTextureMin,
  492.                                   const Vec2& rkTextureMax, Vec2* akTexture)
  493. {
  494.         Vec2 kTextureRange = rkTextureMax - rkTextureMin;
  495.         int iMMax = (m_bClosed ? m_iMedialSamples : m_iMedialSamples - 1);
  496.         for (int iM = 0, iV = 0; iM <= iMMax; iM++)
  497.         {
  498.                 float fMRatio = ((float)iM) / ((float)iMMax);
  499.                 float fMValue = rkTextureMin.y + fMRatio * kTextureRange.y;
  500.                 for (int iS = 0; iS <= m_iSliceSamples; iS++)
  501.                 {
  502.                         float fSRatio = ((float)iS) / ((float)m_iSliceSamples);
  503.                         float fSValue = rkTextureMin.x + fSRatio * kTextureRange.x;
  504.                         akTexture[iV].x = fSValue;
  505.                         akTexture[iV].y = fMValue;
  506.                         iV++;
  507.                 }
  508.         }
  509. }
  510. //----------------------------------------------------------------------------
  511. void TubeSurface::ComputeConnectivity(int& riTQuantity, vtx_idx*& raiConnect, bool bInsideView)
  512. {
  513.         if (m_bClosed)
  514.                 riTQuantity = 2 * m_iSliceSamples * m_iMedialSamples;
  515.         else
  516.                 riTQuantity = 2 * m_iSliceSamples * (m_iMedialSamples - 1);
  517.  
  518.         iNumIndices = riTQuantity * 3;
  519.  
  520.         if (m_bCap)
  521.         {
  522.                 riTQuantity += ((m_iSliceSamples - 2) * 3) * 2;
  523.                 iNumIndices += ((m_iSliceSamples - 2) * 3) * 2;
  524.         }
  525.  
  526.         if (nAllocIndices != iNumIndices)
  527.         {
  528.                 if (raiConnect)
  529.                         delete[]raiConnect;
  530.                 nAllocIndices = iNumIndices;
  531.                 raiConnect = new vtx_idx[nAllocIndices];
  532.         }
  533.  
  534.         int iM, iMStart, i0, i1, i2, i3, i;
  535.         vtx_idx* aiConnect = raiConnect;
  536.         for (iM = 0, iMStart = 0; iM < m_iMedialSamples - 1; iM++)
  537.         {
  538.                 i0 = iMStart;
  539.                 i1 = i0 + 1;
  540.                 iMStart += m_iSliceSamples + 1;
  541.                 i2 = iMStart;
  542.                 i3 = i2 + 1;
  543.                 for (i = 0; i < m_iSliceSamples; i++, aiConnect += 6)
  544.                 {
  545.                         if (bInsideView)
  546.                         {
  547.                                 aiConnect[0] = i0++;
  548.                                 aiConnect[1] = i2;
  549.                                 aiConnect[2] = i1;
  550.                                 aiConnect[3] = i1++;
  551.                                 aiConnect[4] = i2++;
  552.                                 aiConnect[5] = i3++;
  553.                         }
  554.                         else  // outside view
  555.                         {
  556.                                 aiConnect[0] = i0++;
  557.                                 aiConnect[1] = i1;
  558.                                 aiConnect[2] = i2;
  559.                                 aiConnect[3] = i1++;
  560.                                 aiConnect[4] = i3++;
  561.                                 aiConnect[5] = i2++;
  562.  
  563.                                 if (Cry3DEngineBase::GetCVars()->e_Ropes == 2)
  564.                                 {
  565.                                         ColorB col = ColorB(100, 100, 0, 50);
  566.                                         gEnv->pRenderer->GetIRenderAuxGeom()->DrawTriangle(m_worldTM * m_akVertex[aiConnect[0]], col, m_worldTM * m_akVertex[aiConnect[1]], col, m_worldTM * m_akVertex[aiConnect[2]], col);
  567.                                         col = ColorB(100, 0, 100, 50);
  568.                                         gEnv->pRenderer->GetIRenderAuxGeom()->DrawTriangle(m_worldTM * m_akVertex[aiConnect[3]], col, m_worldTM * m_akVertex[aiConnect[4]], col, m_worldTM * m_akVertex[aiConnect[5]], col);
  569.                                 }
  570.                         }
  571.                 }
  572.         }
  573.  
  574.         if (m_bClosed)
  575.         {
  576.                 i0 = iMStart;
  577.                 i1 = i0 + 1;
  578.                 i2 = 0;
  579.                 i3 = i2 + 1;
  580.                 for (i = 0; i < m_iSliceSamples; i++, aiConnect += 6)
  581.                 {
  582.                         if (bInsideView)
  583.                         {
  584.                                 aiConnect[0] = i0++;
  585.                                 aiConnect[1] = i2;
  586.                                 aiConnect[2] = i1;
  587.                                 aiConnect[3] = i1++;
  588.                                 aiConnect[4] = i2++;
  589.                                 aiConnect[5] = i3++;
  590.                         }
  591.                         else  // outside view
  592.                         {
  593.                                 aiConnect[0] = i0++;
  594.                                 aiConnect[1] = i1;
  595.                                 aiConnect[2] = i2;
  596.                                 aiConnect[3] = i1++;
  597.                                 aiConnect[4] = i3++;
  598.                                 aiConnect[5] = i2++;
  599.                         }
  600.                 }
  601.         }
  602.         else if (m_bCap)
  603.         {
  604.                 i0 = 0;
  605.                 i1 = 1;
  606.                 i2 = 2;
  607.                 // Begining Cap.
  608.                 for (i = 0; i < m_iSliceSamples - 2; i++, aiConnect += 3)
  609.                 {
  610.                         aiConnect[0] = i0;
  611.                         aiConnect[1] = i2++;
  612.                         aiConnect[2] = i1++;
  613.                 }
  614.                 i0 = iMStart;
  615.                 i1 = i0 + 1;
  616.                 i2 = i0 + 2;
  617.                 // Ending Cap.
  618.                 for (i = 0; i < m_iSliceSamples - 2; i++, aiConnect += 3)
  619.                 {
  620.                         aiConnect[0] = i0;
  621.                         aiConnect[1] = i1++;
  622.                         aiConnect[2] = i2++;
  623.                 }
  624.         }
  625. }
  626.  
  627. /*
  628.    //----------------------------------------------------------------------------
  629.    void TubeSurface::GetTMinSlice (Vec3* akSlice)
  630.    {
  631.    for (int i = 0; i <= m_iSliceSamples; i++)
  632.     akSlice[i] = m_akVertex[i];
  633.    }
  634.    //----------------------------------------------------------------------------
  635.    void TubeSurface::GetTMaxSlice (Vec3* akSlice)
  636.    {
  637.    int j = m_iVertexQuantity - m_iSliceSamples - 1;
  638.    for (int i = 0; i <= m_iSliceSamples; i++, j++)
  639.     akSlice[i] = m_akVertex[j];
  640.    }
  641.    //----------------------------------------------------------------------------
  642.    void TubeSurface::UpdateSurface ()
  643.    {
  644.    ComputeVertices(m_akVertex);
  645.    if ( m_akNormal )
  646.     ComputeNormals(m_akVertex,m_akNormal);
  647.    }
  648.  */
  649. //----------------------------------------------------------------------------
  650.  
  651. //////////////////////////////////////////////////////////////////////////
  652. // Every Rope will keep a pointer to this and increase reference count.
  653. //////////////////////////////////////////////////////////////////////////
  654. class CRopeSurfaceCache : public _i_reference_target_t
  655. {
  656. public:
  657.         static CRopeSurfaceCache* GetSurfaceCache();
  658.         static void               ReleaseSurfaceCache(CRopeSurfaceCache* cache);
  659.  
  660.         static void               CleanupCaches();
  661.  
  662. public:
  663.         struct GetLocalCache
  664.         {
  665.                 GetLocalCache()
  666.                         : pCache(CRopeSurfaceCache::GetSurfaceCache())
  667.                 {}
  668.  
  669.                 ~GetLocalCache()
  670.                 {
  671.                         CRopeSurfaceCache::ReleaseSurfaceCache(pCache);
  672.                 }
  673.  
  674.                 CRopeSurfaceCache* pCache;
  675.  
  676.         private:
  677.                 GetLocalCache(const GetLocalCache&);
  678.                 GetLocalCache& operator=(const GetLocalCache&);
  679.         };
  680.  
  681. public:
  682.         TubeSurface tubeSurface;
  683.  
  684.         CRopeSurfaceCache() {};
  685.         ~CRopeSurfaceCache() {}
  686.  
  687. private:
  688.         static CryCriticalSectionNonRecursive  g_CacheLock;
  689.         static std::vector<CRopeSurfaceCache*> g_CachePool;
  690. };
  691.  
  692. CryCriticalSectionNonRecursive CRopeSurfaceCache::g_CacheLock;
  693. std::vector<CRopeSurfaceCache*> CRopeSurfaceCache::g_CachePool;
  694.  
  695. CRopeSurfaceCache* CRopeSurfaceCache::GetSurfaceCache()
  696. {
  697.         CryAutoLock<CryCriticalSectionNonRecursive> lock(g_CacheLock);
  698.  
  699.         CRopeSurfaceCache* ret = NULL;
  700.  
  701.         if (g_CachePool.empty())
  702.         {
  703.                 ret = new CRopeSurfaceCache;
  704.         }
  705.         else
  706.         {
  707.                 ret = g_CachePool.back();
  708.                 g_CachePool.pop_back();
  709.         }
  710.  
  711.         return ret;
  712. }
  713.  
  714. void CRopeSurfaceCache::ReleaseSurfaceCache(CRopeSurfaceCache* cache)
  715. {
  716.         CryAutoLock<CryCriticalSectionNonRecursive> lock(g_CacheLock);
  717.         g_CachePool.push_back(cache);
  718. }
  719.  
  720. void CRopeSurfaceCache::CleanupCaches()
  721. {
  722.         CryAutoLock<CryCriticalSectionNonRecursive> lock(g_CacheLock);
  723.  
  724.         for (std::vector<CRopeSurfaceCache*>::iterator it = g_CachePool.begin(), itEnd = g_CachePool.end(); it != itEnd; ++it)
  725.                 delete *it;
  726.  
  727.         stl::free_container(g_CachePool);
  728. }
  729.  
  730. //////////////////////////////////////////////////////////////////////////
  731. CRopeRenderNode::CRopeRenderNode()
  732.         : m_pos(0, 0, 0)
  733.         , m_localBounds(Vec3(-1, -1, -1), Vec3(1, 1, 1))
  734.         , m_pRenderMesh(0)
  735.         , m_pMaterial(0)
  736.         , m_pPhysicalEntity(0)
  737.         , m_nLinkedEndsMask(0)
  738. {
  739.         GetInstCount(GetRenderNodeType())++;
  740.  
  741.         m_pMaterial = GetMatMan()->GetDefaultMaterial();
  742.  
  743.         m_sName.Format("Rope_%p", this);
  744.  
  745.         memset(&m_params, 0, sizeof(m_params));
  746.         m_params.nMaxIters = 650;
  747.         m_params.maxTimeStep = 0.02f;
  748.         m_params.stiffness = 10.0f;
  749.         m_params.damping = 0.2f;
  750.         m_params.sleepSpeed = 0.04f;
  751.  
  752.         m_bModified = true;
  753.         m_bRopeCreatedInsideVisArea = false;
  754.  
  755.         m_worldTM.SetIdentity();
  756.         m_InvWorldTM.SetIdentity();
  757.         m_WSBBox.min = Vec3(0, 0, 0);
  758.         m_WSBBox.max = Vec3(1, 1, 1);
  759.         m_bNeedToReRegister = true;
  760.         m_bStaticPhysics = false;
  761.         m_nEntityOwnerId = 0;
  762. }
  763.  
  764. //////////////////////////////////////////////////////////////////////////
  765. CRopeRenderNode::~CRopeRenderNode()
  766. {
  767.         GetInstCount(GetRenderNodeType())--;
  768.  
  769.         StopRopeSound();
  770.         Dephysicalize();
  771.         Get3DEngine()->FreeRenderNodeState(this);
  772.         m_pRenderMesh = NULL;
  773. }
  774.  
  775. //////////////////////////////////////////////////////////////////////////
  776. void CRopeRenderNode::StaticReset()
  777. {
  778.         CRopeSurfaceCache::CleanupCaches();
  779. }
  780.  
  781. //////////////////////////////////////////////////////////////////////////
  782. void CRopeRenderNode::GetLocalBounds(AABB& bbox)
  783. {
  784.         bbox = m_localBounds;
  785. };
  786.  
  787. //////////////////////////////////////////////////////////////////////////
  788. void CRopeRenderNode::SetMatrix(const Matrix34& mat)
  789. {
  790.         m_worldTM = mat;
  791.         m_InvWorldTM = m_worldTM.GetInverted();
  792.         m_pos = mat.GetTranslation();
  793.  
  794.         m_WSBBox.SetTransformedAABB(mat, m_localBounds);
  795.  
  796.         Get3DEngine()->RegisterEntity(this);
  797.         m_bNeedToReRegister = false;
  798.  
  799.         if (!m_pPhysicalEntity)
  800.                 Physicalize();
  801.         else
  802.         {
  803.                 // Just move physics.
  804.                 pe_params_pos par_pos;
  805.                 par_pos.pMtx3x4 = &m_worldTM;
  806.                 m_pPhysicalEntity->SetParams(&par_pos);
  807.  
  808.                 IVisArea* pVisArea = GetEntityVisArea();
  809.                 if ((pVisArea != 0) != m_bRopeCreatedInsideVisArea)
  810.                 {
  811.                         // Rope moved between vis area and outside.
  812.                         m_bRopeCreatedInsideVisArea = pVisArea != 0;
  813.  
  814.                         pe_params_flags par_flags;
  815.                         if (m_params.nFlags & eRope_CheckCollisinos)
  816.                         {
  817.                                 // If we are inside vis/area disable terrain collisions.
  818.                                 if (!m_bRopeCreatedInsideVisArea)
  819.                                         par_flags.flagsOR = rope_collides_with_terrain;
  820.                                 else
  821.                                         par_flags.flagsAND = ~rope_collides_with_terrain;
  822.                         }
  823.                         m_pPhysicalEntity->SetParams(&par_flags);
  824.                 }
  825.         }
  826. }
  827.  
  828. //////////////////////////////////////////////////////////////////////////
  829. const char* CRopeRenderNode::GetEntityClassName() const
  830. {
  831.         return "RopeEntity";
  832. }
  833.  
  834. //////////////////////////////////////////////////////////////////////////
  835. void CRopeRenderNode::SetName(const char* sName)
  836. {
  837.         m_sName = sName;
  838. }
  839.  
  840. //////////////////////////////////////////////////////////////////////////
  841. const char* CRopeRenderNode::GetName() const
  842. {
  843.         return m_sName;
  844. }
  845.  
  846. //////////////////////////////////////////////////////////////////////////
  847. void CRopeRenderNode::Render(const SRendParams& rParams, const SRenderingPassInfo& passInfo)
  848. {
  849.         FUNCTION_PROFILER_3DENGINE;
  850.  
  851.         if (GetCVars()->e_Ropes == 0 || (m_dwRndFlags & ERF_HIDDEN) || m_pMaterial == NULL)
  852.                 return; // false;
  853.  
  854.         if (GetCVars()->e_Ropes == 2)
  855.         {
  856.                 UpdateRenderMesh();
  857.                 return; // true;
  858.         }
  859.  
  860.         if (m_bModified)
  861.                 UpdateRenderMesh();
  862.  
  863.         if (!m_pRenderMesh || m_pRenderMesh->GetVerticesCount() <= 3)
  864.                 return; // false;
  865.  
  866.         IRenderer* pRend = GetRenderer();
  867.  
  868.         CRenderObject* pObj = pRend->EF_GetObject_Temp(passInfo.ThreadID());
  869.         if (!pObj)
  870.                 return; // false;
  871.         pObj->m_pRenderNode = this;
  872.         pObj->m_DissolveRef = rParams.nDissolveRef;
  873.         pObj->m_ObjFlags |= FOB_TRANS_MASK | rParams.dwFObjFlags;
  874.         pObj->m_fAlpha = rParams.fAlpha;
  875.         pObj->m_II.m_AmbColor = rParams.AmbientColor;
  876.         pObj->m_II.m_Matrix = m_worldTM;
  877.  
  878.         pObj->m_ObjFlags |= FOB_INSHADOW;
  879.  
  880.         ////////////////////////////////////////////////////////////////////////////////////////////////////
  881.         // Set render quality
  882.         ////////////////////////////////////////////////////////////////////////////////////////////////////
  883.         pObj->m_fDistance = rParams.fDistance;
  884.  
  885.         ////////////////////////////////////////////////////////////////////////////////////////////////////
  886.         // Add render elements
  887.         ////////////////////////////////////////////////////////////////////////////////////////////////////
  888.  
  889.         if (rParams.pMaterial)
  890.                 pObj->m_pCurrMaterial = rParams.pMaterial;
  891.         else
  892.                 pObj->m_pCurrMaterial = m_pMaterial;
  893.  
  894.         pObj->m_nMaterialLayers = m_nMaterialLayers;
  895.  
  896.         //////////////////////////////////////////////////////////////////////////
  897.         if (GetCVars()->e_DebugDraw)
  898.         {
  899.                 RenderDebugInfo(rParams, passInfo);
  900.         }
  901.         //////////////////////////////////////////////////////////////////////////
  902.  
  903.         m_pRenderMesh->Render(pObj, passInfo);
  904. }
  905.  
  906. //////////////////////////////////////////////////////////////////////////
  907. bool CRopeRenderNode::RenderDebugInfo(const SRendParams& rParams, const SRenderingPassInfo& passInfo)
  908. {
  909.         if (passInfo.IsShadowPass())
  910.                 return false;
  911.  
  912.         //      bool bVerbose = GetCVars()->e_DebugDraw > 1;
  913.         bool bOnlyBoxes = GetCVars()->e_DebugDraw < 0;
  914.  
  915.         if (bOnlyBoxes)
  916.                 return true;
  917.  
  918.         Vec3 pos = m_worldTM.GetTranslation();
  919.  
  920.         int nTris = m_pRenderMesh->GetIndicesCount() / 3;
  921.         // text
  922.         float color[4] = { 0, 1, 1, 1 };
  923.  
  924.         if (GetCVars()->e_DebugDraw == 2)          // color coded polygon count
  925.                 IRenderAuxText::DrawLabelExF(pos, 1.3f, color, true, true, "%d", nTris);
  926.         else if (GetCVars()->e_DebugDraw == 5)  // number of render materials (color coded)
  927.                 IRenderAuxText::DrawLabelEx(pos, 1.3f, color, true, true, "1");
  928.  
  929.         return true;
  930. }
  931.  
  932. //////////////////////////////////////////////////////////////////////////
  933. IPhysicalEntity* CRopeRenderNode::GetPhysics() const
  934. {
  935.         return m_pPhysicalEntity;
  936. }
  937.  
  938. //////////////////////////////////////////////////////////////////////////
  939. void CRopeRenderNode::SetPhysics(IPhysicalEntity* pPhysicalEntity)
  940. {
  941.         m_pPhysicalEntity = pPhysicalEntity;
  942.         m_bStaticPhysics = pPhysicalEntity->GetType() != PE_ROPE;
  943.         pe_params_foreign_data pfd;
  944.         pfd.pForeignData = (IRenderNode*)this;
  945.         pfd.iForeignData = PHYS_FOREIGN_ID_ROPE;
  946.         pPhysicalEntity->SetParams(&pfd, 1);
  947.  
  948.         pe_params_rope pr;
  949.         pPhysicalEntity->GetParams(&pr);
  950.         m_points.resize(2);
  951.         m_points[0] = pr.pPoints[0];
  952.         m_points[1] = pr.pPoints[pr.nSegments];
  953.         SyncWithPhysicalRope(true);
  954. }
  955.  
  956. //////////////////////////////////////////////////////////////////////////
  957. void CRopeRenderNode::Physicalize(bool bInstant)
  958. {
  959.         if (m_params.mass <= 0)
  960.                 m_bStaticPhysics = true;
  961.         else
  962.                 m_bStaticPhysics = false;
  963.  
  964.         if (!m_pPhysicalEntity || (m_pPhysicalEntity->GetType() == PE_ROPE) != (m_params.mass > 0))
  965.         {
  966.                 if (m_pPhysicalEntity)
  967.                         gEnv->pPhysicalWorld->DestroyPhysicalEntity(m_pPhysicalEntity);
  968.                 m_pPhysicalEntity = gEnv->pPhysicalWorld->CreatePhysicalEntity((m_bStaticPhysics) ? PE_STATIC : PE_ROPE,
  969.                                                                                NULL, (IRenderNode*)this, PHYS_FOREIGN_ID_ROPE, m_nEntityOwnerId ? (m_nEntityOwnerId & 0xFFFF) : -1);
  970.                 if (!m_pPhysicalEntity)
  971.                         return;
  972.         }
  973.  
  974.         if (m_points.size() < 2 || m_params.nPhysSegments < 1)
  975.                 return;
  976.  
  977.         pe_params_pos par_pos;
  978.         par_pos.pMtx3x4 = &m_worldTM;
  979.         m_pPhysicalEntity->SetParams(&par_pos);
  980.  
  981.         int surfaceTypesId[MAX_SUB_MATERIALS];
  982.         memset(surfaceTypesId, 0, sizeof(surfaceTypesId));
  983.         surfaceTypesId[0] = 0;
  984.         if (m_pMaterial)
  985.                 m_pMaterial->FillSurfaceTypeIds(surfaceTypesId);
  986.  
  987.         Vec3* pSrcPoints = &m_points[0];
  988.         int nSrcPoints = (int)m_points.size();
  989.         int nSrcSegments = nSrcPoints - 1;
  990.  
  991.         m_physicsPoints.resize(m_params.nPhysSegments + 1);
  992.         int nPoints = (int)m_physicsPoints.size();
  993.         int nTargetSegments = nPoints - 1;
  994.         int i;
  995.  
  996.         //////////////////////////////////////////////////////////////////////////
  997.         // Set physical ropes params.
  998.         pe_params_rope pr;
  999.  
  1000.         pr.nSegments = nTargetSegments;
  1001.         pr.pPoints = strided_pointer<Vec3>(&m_physicsPoints[0]);
  1002.         pr.length = 0;
  1003.  
  1004.         pr.pEntTiedTo[0] = 0;
  1005.         pr.pEntTiedTo[1] = 0;
  1006.  
  1007.         // Calc original length.
  1008.         for (i = 0; i < nSrcPoints - 1; i++)
  1009.         {
  1010.                 pr.length += (pSrcPoints[i + 1] - pSrcPoints[i]).GetLength();
  1011.         }
  1012.  
  1013.         // Make rope segments of equal length.
  1014.         if (nSrcPoints == 2 && m_params.tension < 0)
  1015.         {
  1016.                 int idir, ibound[2] = { 0, 128 };
  1017.                 double h, s, L, a, k, ra, seglen, rh, abound[2], x;
  1018.                 Vec3 origin, axisx;
  1019.                 static double g_atab[128];
  1020.                 static int g_bTabFilled = 0;
  1021.  
  1022.                 h = fabs_tpl(pSrcPoints[0].z - pSrcPoints[1].z);
  1023.                 s = (Vec2(pSrcPoints[0]) - Vec2(pSrcPoints[1])).GetLength();
  1024.                 L = (pSrcPoints[0] - pSrcPoints[1]).GetLength() * (1 - m_params.tension);
  1025.                 if (h < s * 0.0001)
  1026.                 {
  1027.                         // will solve for 2*a*sinh(s/(2*a)) == L
  1028.                         rh = L;
  1029.                         k = 0;
  1030.                 }
  1031.                 else
  1032.                 {
  1033.                         // will solve for 2*a*sinh(L/(2*a)) == h/sinh(k)
  1034.                         k = h / L;
  1035.                         k = log_tpl((1 + k) / (1 - k)) * 0.5; // k = atanh(k)
  1036.                         rh = h / sinh(k);
  1037.                 }
  1038.                 if (!g_bTabFilled)
  1039.                         for (i = 0, a = 0.125, g_bTabFilled = 1; i < 128; i++, a += (8.0 / 128))
  1040.                                 g_atab[i] = 2 * a * sinh(1 / (2 * a));
  1041.                 ibound[0] = 0;
  1042.                 ibound[1] = 127;
  1043.                 do
  1044.                 {
  1045.                         i = (ibound[0] + ibound[1]) >> 1;
  1046.                         ibound[isneg(g_atab[i] * s - L)] = i;
  1047.                 }
  1048.                 while (ibound[1] > ibound[0] + 1);
  1049.                 abound[1] = (abound[0] = (ibound[0] * (8.0 / 128) + 0.125) * s) * 2;
  1050.                 i = 0;
  1051.                 do
  1052.                 {
  1053.                         a = (abound[0] + abound[1]) * 0.5;
  1054.                         x = 2 * a * sinh(s / (2 * a)) - rh;
  1055.                         abound[isneg(x)] = a;
  1056.                 }
  1057.                 while (++i < 16);
  1058.                 ra = 1 / (a = (abound[0] + abound[1]) * 0.5);
  1059.  
  1060.                 idir = isneg(pSrcPoints[0].z - pSrcPoints[1].z);
  1061.                 pr.pPoints[0] = pSrcPoints[0];
  1062.                 pr.pPoints[nTargetSegments] = pSrcPoints[1];
  1063.                 (axisx = (Vec2(pSrcPoints[idir ^ 1]) - Vec2(pSrcPoints[idir])) / s).z = 0;
  1064.                 origin = (pSrcPoints[0] + pSrcPoints[1]) * 0.5;
  1065.                 origin.z = pSrcPoints[idir].z;
  1066.                 origin += axisx * (a * k);
  1067.                 x = -s * 0.5 - a * k;
  1068.                 origin.z -= a * cosh(x * ra);
  1069.                 seglen = L / nTargetSegments;
  1070.                 for (i = 1; i < nTargetSegments; i++)
  1071.                 {
  1072.                         x = seglen * ra + sinh(x * ra);
  1073.                         x = log(x + sqrt(x * x + 1)) * a; // x = asinh(x)*a;
  1074.                         pr.pPoints[(nTargetSegments & - idir) + i - (i & - idir) * 2] = origin + axisx * x + Vec3(0, 0, 1) * a * cosh(x * ra);
  1075.                 }
  1076.         }
  1077.         else
  1078.         {
  1079.                 int iter, ivtx;
  1080.                 float ka, kb, kc, kd;
  1081.                 float rnSegs = 1.0f / nTargetSegments;
  1082.                 float len = pr.length;
  1083.  
  1084.                 Vec3 dir, v0;
  1085.  
  1086.                 iter = 3;
  1087.                 do
  1088.                 {
  1089.                         pr.pPoints[0] = pSrcPoints[0];
  1090.                         for (i = ivtx = 0; i < nTargetSegments && ivtx < nSrcSegments; )
  1091.                         {
  1092.                                 dir = pSrcPoints[ivtx + 1] - pSrcPoints[ivtx];
  1093.                                 v0 = pSrcPoints[ivtx] - pr.pPoints[i];
  1094.                                 ka = dir.GetLengthSquared();
  1095.                                 kb = v0 * dir;
  1096.                                 kc = v0.GetLengthSquared() - sqr(len * rnSegs);
  1097.                                 kd = sqrt_tpl(max(0.0f, kb * kb - ka * kc));
  1098.                                 if (kd - kb < ka)
  1099.                                         pr.pPoints[++i] = pSrcPoints[ivtx] + dir * ((kd - kb) / ka);
  1100.                                 else
  1101.                                         ++ivtx;
  1102.                         }
  1103.                         len *= (1.0f - (nTargetSegments - i) * rnSegs);
  1104.                         len += (pSrcPoints[nSrcSegments] - pr.pPoints[i]).GetLength();
  1105.                 }
  1106.                 while (--iter);
  1107.                 pr.pPoints[nTargetSegments] = pSrcPoints[nSrcSegments]; // copy last point
  1108.                 dir = pr.pPoints[nTargetSegments] - pr.pPoints[i];
  1109.                 if (i + 1 < nTargetSegments)
  1110.                 {
  1111.                         for (ivtx = i + 1, rnSegs = 1.0f / (nTargetSegments - i); ivtx < nTargetSegments; ivtx++)
  1112.                         {
  1113.                                 pr.pPoints[ivtx] = pr.pPoints[i] + dir * ((ivtx - i) * rnSegs);
  1114.                         }
  1115.                 }
  1116.                 // Update length.
  1117.                 pr.length = 0;
  1118.                 for (i = 0; i < nPoints - 1; i++)
  1119.                 {
  1120.                         pr.length += (pr.pPoints[i + 1] - pr.pPoints[i]).GetLength();
  1121.                 }
  1122.         }
  1123.  
  1124.         // Transform to world space.
  1125.         for (i = 0; i < nPoints; i++)
  1126.         {
  1127.                 pr.pPoints[i] = m_worldTM.TransformPoint(pr.pPoints[i]);
  1128.         }
  1129.  
  1130.         if (!m_bStaticPhysics)
  1131.         {
  1132.                 //////////////////////////////////////////////////////////////////////////
  1133.                 pe_params_flags par_flags;
  1134.                 par_flags.flags = pef_never_affect_triggers | pef_log_state_changes | pef_log_poststep;
  1135.                 if (m_params.nFlags & eRope_Subdivide)
  1136.                         par_flags.flags |= rope_subdivide_segs;
  1137.                 if (m_params.nFlags & eRope_CheckCollisinos)
  1138.                 {
  1139.                         par_flags.flags |= rope_collides;
  1140.                         if (m_params.nFlags & eRope_NoAttachmentCollisions)
  1141.                                 par_flags.flags |= rope_ignore_attachments;
  1142.                         // If we are inside vis/area disable terrain collisions.
  1143.                         if (!m_bRopeCreatedInsideVisArea)
  1144.                         {
  1145.                                 par_flags.flags |= rope_collides_with_terrain;
  1146.                         }
  1147.                 }
  1148.                 par_flags.flags |= rope_traceable;
  1149.                 if (m_params.mass <= 0)
  1150.                         par_flags.flags |= pef_disabled;
  1151.                 par_flags.flags |= rope_no_tears & - isneg(m_params.maxForce);
  1152.                 m_pPhysicalEntity->SetParams(&par_flags);
  1153.  
  1154.                 pr.mass = m_params.mass;
  1155.                 pr.airResistance = m_params.airResistance;
  1156.                 pr.collDist = m_params.fThickness;
  1157.                 pr.sensorRadius = m_params.fAnchorRadius;
  1158.                 pr.maxForce = fabsf(m_params.maxForce);
  1159.                 pr.jointLimit = m_params.jointLimit;
  1160.                 pr.friction = m_params.friction;
  1161.                 pr.frictionPull = m_params.frictionPull;
  1162.                 pr.wind = m_params.wind;
  1163.                 pr.windVariance = m_params.windVariance;
  1164.                 pr.nMaxSubVtx = m_params.nMaxSubVtx;
  1165.                 pr.surface_idx = surfaceTypesId[0];
  1166.                 pr.maxIters = m_params.nMaxIters;
  1167.                 pr.stiffness = m_params.stiffness;
  1168.                 pr.penaltyScale = m_params.hardness;
  1169.  
  1170.                 AnchorEndPoints(pr);
  1171.  
  1172.                 if (m_params.tension != 0)
  1173.                         pr.length *= 1 - m_params.tension;
  1174.                 else if (nSrcPoints == 2)
  1175.                         pr.length *= 0.999f;
  1176.  
  1177.                 m_pPhysicalEntity->SetParams(&pr);
  1178.                 //////////////////////////////////////////////////////////////////////////
  1179.  
  1180.                 // After creation rope is put to sleep, will be awaked on first render after modify.
  1181.                 pe_action_awake pa;
  1182.                 pa.bAwake = m_params.nFlags & eRope_Awake ? 1 : 0;
  1183.                 m_pPhysicalEntity->Action(&pa);
  1184.  
  1185.                 pe_simulation_params simparams;
  1186.                 simparams.maxTimeStep = m_params.maxTimeStep;
  1187.                 simparams.damping = m_params.damping;
  1188.                 simparams.minEnergy = sqr(m_params.sleepSpeed);
  1189.                 m_pPhysicalEntity->SetParams(&simparams);
  1190.  
  1191.                 m_bRopeCreatedInsideVisArea = GetEntityVisArea() != 0;
  1192.  
  1193.                 if (m_params.nFlags & eRope_NoPlayerCollisions)
  1194.                 {
  1195.                         pe_params_collision_class pcs;
  1196.                         pcs.collisionClassOR.ignore = collision_class_living;
  1197.                         m_pPhysicalEntity->SetParams(&pcs);
  1198.                 }
  1199.         }
  1200.         else
  1201.         {
  1202.                 primitives::capsule caps;
  1203.                 pe_params_pos pp;
  1204.                 IGeomManager* pGeoman = gEnv->pPhysicalWorld->GetGeomManager();
  1205.                 phys_geometry* pgeom;
  1206.                 pe_geomparams gp;
  1207.                 pp.pos = pr.pPoints[0];
  1208.                 m_pPhysicalEntity->SetParams(&pp);
  1209.                 caps.r = m_params.fThickness;
  1210.  
  1211.                 /*
  1212.                    m_pPhysicalEntity->RemoveGeometry()
  1213.                    for(i=0; i<nPoints-1; i++)
  1214.                    {
  1215.                    caps.axis = pr.pPoints[i+1]-pr.pPoints[i];
  1216.                    caps.axis /= (caps.hh = caps.axis.len());    caps.hh *= 0.5f;
  1217.                    caps.center = (pr.pPoints[i+1]+pr.pPoints[i])*0.5f-pr.pPoints[0];
  1218.                    pgeom = pGeoman->RegisterGeometry(pGeoman->CreatePrimitive(primitives::capsule::type, &caps), surfaceTypesId[0]);
  1219.                    pgeom->nRefCount = 0;        // we want it to be deleted together with the physical entity
  1220.                    m_pPhysicalEntity->AddGeometry(pgeom, &gp);
  1221.                    }
  1222.                  */
  1223.                 pe_action_remove_all_parts removeall;
  1224.                 m_pPhysicalEntity->Action(&removeall);
  1225.  
  1226.                 int numSplinePoints = m_points.size();
  1227.                 m_spline.resize(numSplinePoints);
  1228.                 for (int pnt = 0; pnt < numSplinePoints; pnt++)
  1229.                 {
  1230.                         m_spline.key(pnt).flags = 0;
  1231.                         m_spline.time(pnt) = (float)pnt / (numSplinePoints - 1);
  1232.                         m_spline.value(pnt) = m_points[pnt];
  1233.                 }
  1234.  
  1235.                 int nLengthSamples = m_params.nNumSegments + 1;
  1236.                 if (!(m_params.nFlags & IRopeRenderNode::eRope_Smooth))
  1237.                         nLengthSamples = m_params.nPhysSegments + 1;
  1238.  
  1239.                 Vec3 p0 = m_points[0];
  1240.                 Vec3 p1;
  1241.  
  1242.                 for (i = 1; i < nLengthSamples; i++)
  1243.                 {
  1244.                         m_spline.interpolate((float)i / (nLengthSamples - 1), p1);
  1245.                         caps.axis = p1 - p0;
  1246.                         caps.axis /= (caps.hh = caps.axis.len());
  1247.                         caps.hh *= 0.5f;
  1248.                         caps.center = (p1 + p0) * 0.5f - m_points[0];
  1249.                         IGeometry* pGeom = pGeoman->CreatePrimitive(primitives::capsule::type, &caps);
  1250.                         pgeom = pGeoman->RegisterGeometry(pGeom, surfaceTypesId[0]);
  1251.                         pGeom->Release();
  1252.                         pgeom->nRefCount = 0; // we want it to be deleted together with the physical entity
  1253.                         m_pPhysicalEntity->AddGeometry(pgeom, &gp);
  1254.                         p0 = p1;
  1255.                 }
  1256.         }
  1257.  
  1258.         m_WSBBox.Reset();
  1259.         for (uint i = 0; i < m_points.size(); i++)
  1260.                 m_WSBBox.Add(m_worldTM.TransformPoint(m_points[i]));
  1261.         m_WSBBox.Expand(Vec3(m_params.fThickness));
  1262.  
  1263.         m_bModified = true;
  1264. }
  1265.  
  1266. //////////////////////////////////////////////////////////////////////////
  1267. void CRopeRenderNode::LinkEndPoints()
  1268. {
  1269.         if (m_pPhysicalEntity)
  1270.         {
  1271.                 if (m_params.mass > 0)
  1272.                 {
  1273.                         pe_params_flags par_flags;
  1274.                         par_flags.flagsOR = pef_disabled;
  1275.                         m_pPhysicalEntity->SetParams(&par_flags); // To prevent rope from awakining objects on linking.
  1276.                 }
  1277.  
  1278.                 pe_params_rope pr, pr1;
  1279.                 Vec3 ptend[2] = { m_worldTM* m_points[0], m_worldTM * m_points[m_points.size() - 1] };
  1280.                 pr1.nSegments = 1;
  1281.                 pr1.pPoints.data = ptend;
  1282.                 if (m_pPhysicalEntity->GetParams(&pr1) && pr1.nSegments)
  1283.                 {
  1284.                         pr.nSegments = pr1.nSegments;
  1285.                         pr.pPoints = pr1.pPoints;
  1286.                 }
  1287.  
  1288.                 pr.pEntTiedTo[0] = 0;
  1289.                 pr.pEntTiedTo[1] = 0;
  1290.                 AnchorEndPoints(pr);
  1291.                 MARK_UNUSED pr.nSegments, pr.pPoints;
  1292.                 m_pPhysicalEntity->SetParams(&pr);
  1293.  
  1294.                 if (m_params.mass > 0 && !(m_params.nFlags & eRope_Disabled))
  1295.                 {
  1296.                         pe_params_flags par_flags;
  1297.                         par_flags.flagsAND = ~pef_disabled;
  1298.                         m_pPhysicalEntity->SetParams(&par_flags);
  1299.                 }
  1300.         }
  1301. }
  1302.  
  1303. //////////////////////////////////////////////////////////////////////////
  1304. void CRopeRenderNode::LinkEndEntities(IPhysicalEntity* pStartEntity, IPhysicalEntity* pEndEntity)
  1305. {
  1306.         m_nLinkedEndsMask = 0;
  1307.  
  1308.         if (!m_pPhysicalEntity || m_params.mass <= 0)
  1309.                 return;
  1310.  
  1311.         if (m_params.mass > 0)
  1312.         {
  1313.                 pe_params_flags par_flags;
  1314.                 par_flags.flagsOR = pef_disabled;
  1315.                 m_pPhysicalEntity->SetParams(&par_flags); // To prevent rope from awakining objects on linking.
  1316.         }
  1317.  
  1318.         pe_params_rope pr;
  1319.  
  1320.         if (pStartEntity)
  1321.         {
  1322.                 pr.pEntTiedTo[0] = pStartEntity;
  1323.                 pr.idPartTiedTo[0] = 0;
  1324.                 m_nLinkedEndsMask |= 0x01;
  1325.         }
  1326.  
  1327.         if (pEndEntity)
  1328.         {
  1329.                 pr.pEntTiedTo[1] = pEndEntity;
  1330.                 pr.idPartTiedTo[1] = 0;
  1331.                 m_nLinkedEndsMask |= 0x02;
  1332.         }
  1333.  
  1334.         m_pPhysicalEntity->SetParams(&pr);
  1335.  
  1336.         if (m_params.mass > 0 && !(m_params.nFlags & eRope_Disabled))
  1337.         {
  1338.                 pe_params_flags par_flags;
  1339.                 par_flags.flagsAND = ~pef_disabled;
  1340.                 m_pPhysicalEntity->SetParams(&par_flags);
  1341.         }
  1342. }
  1343.  
  1344. //////////////////////////////////////////////////////////////////////////
  1345. void CRopeRenderNode::GetEndPointLinks(SEndPointLink* links)
  1346. {
  1347.         links[0].pPhysicalEntity = 0;
  1348.         links[0].offset.Set(0, 0, 0);
  1349.         links[0].nPartId = 0;
  1350.         links[1].pPhysicalEntity = 0;
  1351.         links[1].offset.Set(0, 0, 0);
  1352.         links[1].nPartId = 0;
  1353.  
  1354.         pe_params_rope pr;
  1355.         if (m_pPhysicalEntity)
  1356.         {
  1357.                 m_pPhysicalEntity->GetParams(&pr);
  1358.                 for (int i = 0; i < 2; i++)
  1359.                 {
  1360.                         if (!is_unused(pr.pEntTiedTo[i]) && pr.pEntTiedTo[i])
  1361.                         {
  1362.                                 if (pr.pEntTiedTo[i] == WORLD_ENTITY)
  1363.                                         pr.pEntTiedTo[i] = gEnv->pPhysicalWorld->GetPhysicalEntityById(gEnv->pPhysicalWorld->GetPhysicalEntityId(WORLD_ENTITY));
  1364.                                 links[i].pPhysicalEntity = pr.pEntTiedTo[i];
  1365.                                 links[i].nPartId = pr.idPartTiedTo[i];
  1366.  
  1367.                                 Matrix34 tm;
  1368.                                 pe_status_pos ppos;
  1369.                                 ppos.pMtx3x4 = &tm;
  1370.                                 pr.pEntTiedTo[i]->GetStatus(&ppos);
  1371.                                 tm.Invert();
  1372.                                 links[i].offset = tm.TransformPoint(pr.ptTiedTo[i]); // To local space.
  1373.                         }
  1374.                         else
  1375.                                 links[i].offset = Vec3(0, 0, 0);
  1376.                 }
  1377.         }
  1378. }
  1379.  
  1380. //////////////////////////////////////////////////////////////////////////
  1381. void CRopeRenderNode::AnchorEndPoints(pe_params_rope& pr)
  1382. {
  1383.         m_nLinkedEndsMask = 0;
  1384.         //m_params.fAnchorRadius
  1385.         if (!m_pPhysicalEntity || m_params.mass <= 0)
  1386.                 return;
  1387.  
  1388.         if (m_points.size() < 2)
  1389.                 return;
  1390.  
  1391.         //pr.pEntTiedTo[0] = WORLD_ENTITY;
  1392.         //pr.pEntTiedTo[1] = WORLD_ENTITY;
  1393.         bool bEndsAdjusted = false, bAdjustEnds = m_params.fAnchorRadius > 0.05001f;
  1394.         Vec3 ptend[2] = { pr.pPoints[0], pr.pPoints[pr.nSegments] };
  1395.  
  1396.         primitives::sphere sphPrim;
  1397.  
  1398.         geom_contact* pContacts = 0;
  1399.         sphPrim.center = ptend[0];
  1400.         sphPrim.r = m_params.fAnchorRadius;
  1401.  
  1402.         int collisionEntityTypes = ent_static | ent_sleeping_rigid | ent_rigid | ent_ignore_noncolliding;
  1403.         float d = 0;
  1404.         if (m_params.nFlags & eRope_StaticAttachStart)
  1405.                 pr.pEntTiedTo[0] = WORLD_ENTITY;
  1406.         else
  1407.         {
  1408.                 d = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(sphPrim.type, &sphPrim, Vec3(0, 0, 0), collisionEntityTypes, &pContacts, 0, geom_colltype0, 0);
  1409.                 if (d > 0 && pContacts)
  1410.                 {
  1411.                         IPhysicalEntity* pBindToEntity = gEnv->pPhysicalWorld->GetPhysicalEntityById(pContacts[0].iPrim[0]);
  1412.                         if (pBindToEntity)
  1413.                         {
  1414.                                 pr.pEntTiedTo[0] = pBindToEntity;
  1415.                                 pr.idPartTiedTo[0] = pContacts[0].iPrim[1];
  1416.                                 m_nLinkedEndsMask |= 0x01;
  1417.                                 if (bAdjustEnds && inrange((pContacts->center - sphPrim.center).len2(), sqr(0.01f), sqr(m_params.fAnchorRadius)))
  1418.                                         ptend[0] = pr.ptTiedTo[0] = pContacts->t > 0 ? pContacts->pt : pContacts->center, bEndsAdjusted = true;
  1419.                         }
  1420.                 }
  1421.         }
  1422.  
  1423.         if (m_params.nFlags & eRope_StaticAttachEnd)
  1424.                 pr.pEntTiedTo[1] = WORLD_ENTITY;
  1425.         else
  1426.         {
  1427.                 sphPrim.center = ptend[1];
  1428.                 d = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(sphPrim.type, &sphPrim, Vec3(0, 0, 0), collisionEntityTypes, &pContacts, 0, geom_colltype0, 0);
  1429.                 if (d > 0 && pContacts)
  1430.                 {
  1431.                         IPhysicalEntity* pBindToEntity = gEnv->pPhysicalWorld->GetPhysicalEntityById(pContacts[0].iPrim[0]);
  1432.                         if (pBindToEntity)
  1433.                         {
  1434.                                 pr.pEntTiedTo[1] = pBindToEntity;
  1435.                                 pr.idPartTiedTo[1] = pContacts[0].iPrim[1];
  1436.                                 m_nLinkedEndsMask |= 0x02;
  1437.                                 if (bAdjustEnds && inrange((pContacts->center - sphPrim.center).len2(), sqr(0.01f), sqr(m_params.fAnchorRadius)))
  1438.                                         ptend[1] = pr.ptTiedTo[1] = pContacts->t > 0 ? pContacts->pt : pContacts->center, bEndsAdjusted = true;
  1439.                         }
  1440.                 }
  1441.         }
  1442.  
  1443.         if (bEndsAdjusted && !is_unused(pr.length) &&
  1444.             inrange((pr.pPoints[0] - pr.pPoints[pr.nSegments]).len2(), sqr(pr.length * 0.999f), sqr(pr.length * 1.001f)))
  1445.                 pr.length = (ptend[0] - ptend[1]).len();
  1446. }
  1447.  
  1448. //////////////////////////////////////////////////////////////////////////
  1449. void CRopeRenderNode::Dephysicalize(bool bKeepIfReferenced)
  1450. {
  1451.         // delete old physics
  1452.         if (m_pPhysicalEntity)
  1453.                 gEnv->pPhysicalWorld->DestroyPhysicalEntity(m_pPhysicalEntity);
  1454.         m_pPhysicalEntity = 0;
  1455. }
  1456.  
  1457. //////////////////////////////////////////////////////////////////////////
  1458. void CRopeRenderNode::SetMaterial(IMaterial* pMat)
  1459. {
  1460.         if (!pMat)
  1461.                 pMat = m_pMaterial = GetMatMan()->GetDefaultMaterial();
  1462.         m_pMaterial = pMat;
  1463. }
  1464.  
  1465. //////////////////////////////////////////////////////////////////////////
  1466. void CRopeRenderNode::Precache()
  1467. {
  1468.  
  1469. }
  1470.  
  1471. //////////////////////////////////////////////////////////////////////////
  1472. void CRopeRenderNode::GetMemoryUsage(ICrySizer* pSizer) const
  1473. {
  1474.         SIZER_COMPONENT_NAME(pSizer, "RopeRenderNode");
  1475.         pSizer->AddObject(this, sizeof(*this));
  1476. }
  1477.  
  1478. //////////////////////////////////////////////////////////////////////////
  1479. void CRopeRenderNode::SyncWithPhysicalRope(bool bForce)
  1480. {
  1481.         if (m_bStaticPhysics)
  1482.         {
  1483.                 m_physicsPoints = m_points;
  1484.                 m_WSBBox.Reset();
  1485.                 int numPoints = m_points.size();
  1486.                 for (int i = 0; i < numPoints; i++)
  1487.                 {
  1488.                         Vec3 point = m_points[i];
  1489.                         m_localBounds.Add(point);
  1490.                         point = m_worldTM.TransformPoint(point);
  1491.                         m_WSBBox.Add(point);
  1492.                 }
  1493.                 float r = m_params.fThickness;
  1494.                 m_localBounds.min -= Vec3(r, r, r);
  1495.                 m_localBounds.max += Vec3(r, r, r);
  1496.                 m_WSBBox.min -= Vec3(r, r, r);
  1497.                 m_WSBBox.max += Vec3(r, r, r);
  1498.                 m_bNeedToReRegister = true; // Bounding box was recalculated, rope needs to be registered again 3d engine.
  1499.                 m_bModified = false;
  1500.                 return;
  1501.         }
  1502.         //////////////////////////////////////////////////////////////////////////
  1503.         if (m_pPhysicalEntity)
  1504.         {
  1505.                 pe_status_rope sr;
  1506.                 sr.lock = 1;
  1507.                 if (!m_pPhysicalEntity->GetStatus(&sr))
  1508.                         return;
  1509.                 sr.lock = -1;
  1510.                 int numPoints = sr.nSegments + 1;
  1511.                 if (m_params.nFlags & eRope_Subdivide && sr.nVtx != 0)
  1512.                         numPoints = sr.nVtx;
  1513.                 if (numPoints < 2)
  1514.                 {
  1515.                         m_pPhysicalEntity->GetStatus(&sr); // just to unlock if it was locked
  1516.                         return;
  1517.                 }
  1518.                 m_physicsPoints.resize(numPoints);
  1519.                 m_WSBBox.Reset();
  1520.                 m_localBounds.Reset();
  1521.                 if (m_params.nFlags & eRope_Subdivide && sr.nVtx != 0)
  1522.                         sr.pVtx = &m_physicsPoints[0];
  1523.                 else
  1524.                         sr.pPoints = &m_physicsPoints[0];
  1525.                 m_pPhysicalEntity->GetStatus(&sr);
  1526.                 for (int i = 0; i < numPoints; i++)
  1527.                 {
  1528.                         Vec3 point = m_physicsPoints[i];
  1529.                         m_WSBBox.Add(point);
  1530.                         point = m_InvWorldTM.TransformPoint(point);
  1531.                         m_physicsPoints[i] = point;
  1532.                         m_localBounds.Add(point);
  1533.                 }
  1534.                 float r = m_params.fThickness;
  1535.                 m_localBounds.min -= Vec3(r, r, r);
  1536.                 m_localBounds.max += Vec3(r, r, r);
  1537.                 m_WSBBox.min -= Vec3(r, r, r);
  1538.                 m_WSBBox.max += Vec3(r, r, r);
  1539.                 m_bNeedToReRegister = true; // Bounding box was recalculated, rope needs to be registered again 3d engine.
  1540.         }
  1541.         //////////////////////////////////////////////////////////////////////////
  1542.         m_bModified = false;
  1543. }
  1544.  
  1545. //////////////////////////////////////////////////////////////////////////
  1546. void CRopeRenderNode::CreateRenderMesh()
  1547. {
  1548.         // make new RenderMesh
  1549.         //////////////////////////////////////////////////////////////////////////
  1550.         m_pRenderMesh = GetRenderer()->CreateRenderMeshInitialized(
  1551.           NULL, 3, eVF_P3F_C4B_T2F,
  1552.           NULL, 3, prtTriangleList,
  1553.           "Rope", GetName(),
  1554.           eRMT_Dynamic, 1, 0, NULL, NULL, false, false);
  1555.  
  1556.         CRenderChunk chunk;
  1557.         memset(&chunk, 0, sizeof(chunk));
  1558.         if (m_pMaterial)
  1559.                 chunk.m_nMatFlags = m_pMaterial->GetFlags();
  1560.         chunk.nFirstIndexId = 0;
  1561.         chunk.nFirstVertId = 0;
  1562.         chunk.nNumIndices = 3;
  1563.         chunk.nNumVerts = 3;
  1564.         chunk.m_texelAreaDensity = 1.0f;
  1565.         m_pRenderMesh->SetChunk(0, chunk);
  1566. }
  1567.  
  1568. //////////////////////////////////////////////////////////////////////////
  1569. void CRopeRenderNode::UpdateRenderMesh()
  1570. {
  1571.         FUNCTION_PROFILER_3DENGINE;
  1572.  
  1573.         if (!m_pRenderMesh)
  1574.         {
  1575.                 CreateRenderMesh();
  1576.                 if (!m_pRenderMesh)
  1577.                         return;
  1578.         }
  1579.  
  1580.         if (m_physicsPoints.size() < 2 && !m_bStaticPhysics)
  1581.                 return;
  1582.         if (m_points.size() < 2)
  1583.                 return;
  1584.  
  1585.         SyncWithPhysicalRope(false);
  1586.  
  1587.         //////////////////////////////////////////////////////////////////////////
  1588.         // Tesselate.
  1589.         //////////////////////////////////////////////////////////////////////////
  1590.         int numSplinePoints = m_physicsPoints.size();
  1591.         m_spline.resize(numSplinePoints);
  1592.         for (int pnt = 0; pnt < numSplinePoints; pnt++)
  1593.         {
  1594.                 m_spline.key(pnt).flags = 0;
  1595.                 m_spline.time(pnt) = pnt;
  1596.                 m_spline.value(pnt) = m_physicsPoints[pnt];
  1597.         }
  1598.         m_spline.SetRange(0, m_physicsPoints.size() - 1);
  1599.         m_spline.SetModified(true);
  1600.  
  1601.         int nLengthSamples = m_params.nNumSegments + 1;
  1602.         if (!(m_params.nFlags & IRopeRenderNode::eRope_Smooth))
  1603.                 nLengthSamples = m_params.nPhysSegments + 1;
  1604.  
  1605.         Vec2 vTexMin(0, 0);
  1606.         Vec2 vTexMax(m_params.fTextureTileU, m_params.fTextureTileV);
  1607.  
  1608.         CRopeSurfaceCache::GetLocalCache getCache;
  1609.         TubeSurface& tubeSurf = getCache.pCache->tubeSurface;
  1610.  
  1611.         tubeSurf.m_worldTM = m_worldTM;
  1612.         //tubeSurf.m_worldTM.SetIdentity();
  1613.  
  1614.         tubeSurf.GenerateSurface(&m_spline, m_params.fThickness, false, (m_physicsPoints[numSplinePoints - 1] - m_physicsPoints[0]).GetOrthogonal().GetNormalized(),
  1615.                                  nLengthSamples, m_params.nNumSides, true, false, false, false, &vTexMin, &vTexMax);
  1616.  
  1617.         int nNewVertexCount = tubeSurf.iVQuantity;
  1618.  
  1619.         // Resize vertex buffer.
  1620.         m_pRenderMesh->LockForThreadAccess();
  1621.         m_pRenderMesh->UpdateVertices(NULL, nNewVertexCount, 0, VSF_GENERAL, 0u);
  1622.  
  1623.         int nPosStride = 0;
  1624.         int nUVStride = 0;
  1625.         int nTangsStride = 0;
  1626.  
  1627.         byte* pVertPos = m_pRenderMesh->GetPosPtr(nPosStride, FSL_VIDEO_CREATE);
  1628.         if (!pVertPos)
  1629.                 return;
  1630.         byte* pVertTexUV = m_pRenderMesh->GetUVPtr(nUVStride, FSL_VIDEO_CREATE);
  1631.  
  1632.         byte* pTangents = m_pRenderMesh->GetTangentPtr(nTangsStride, FSL_VIDEO_CREATE);
  1633.  
  1634.         for (int i = 0; i < nNewVertexCount; i++)
  1635.         {
  1636.                 Vec3 vP = Vec3(tubeSurf.m_akVertex[i].x, tubeSurf.m_akVertex[i].y, tubeSurf.m_akVertex[i].z);
  1637.                 Vec2 vT = Vec2(tubeSurf.m_akTexture[i].x, tubeSurf.m_akTexture[i].y);
  1638.  
  1639.                 *((Vec3*)pVertPos) = vP;
  1640.                 *((Vec2*)pVertTexUV) = vT;
  1641.  
  1642.                 *(SPipTangents*)pTangents = SPipTangents(
  1643.                   tubeSurf.m_akTangents[i],
  1644.                   tubeSurf.m_akBitangents[i], 1);
  1645.  
  1646.                 pVertPos += nPosStride;
  1647.                 pVertTexUV += nUVStride;
  1648.                 pTangents += nTangsStride;
  1649.         }
  1650.  
  1651.         m_pRenderMesh->UnlockStream(VSF_GENERAL);
  1652.         m_pRenderMesh->UnlockStream(VSF_TANGENTS);
  1653.         m_pRenderMesh->UpdateIndices(tubeSurf.m_pIndices, tubeSurf.iNumIndices, 0, 0u);
  1654.  
  1655.         // Update chunk params.
  1656.         CRenderChunk* pChunk = &m_pRenderMesh->GetChunks()[0];
  1657.         if (m_pMaterial)
  1658.                 pChunk->m_nMatFlags = m_pMaterial->GetFlags();
  1659.         pChunk->nNumIndices = tubeSurf.iNumIndices;
  1660.         pChunk->nNumVerts = tubeSurf.iVQuantity;
  1661.         m_pRenderMesh->SetChunk(0, *pChunk);
  1662.  
  1663.         m_pRenderMesh->UnLockForThreadAccess();
  1664. }
  1665.  
  1666. //////////////////////////////////////////////////////////////////////////
  1667. void CRopeRenderNode::SetParams(const SRopeParams& params)
  1668. {
  1669.         m_params = params;
  1670.         (m_dwRndFlags &= ~(ERF_CASTSHADOWMAPS | ERF_HAS_CASTSHADOWMAPS)) |= -(params.nFlags & eRope_CastShadows) >> 31 & (ERF_CASTSHADOWMAPS | ERF_HAS_CASTSHADOWMAPS);
  1671. }
  1672.  
  1673. //////////////////////////////////////////////////////////////////////////
  1674. const CRopeRenderNode::SRopeParams& CRopeRenderNode::GetParams() const
  1675. {
  1676.         return m_params;
  1677. }
  1678.  
  1679. //////////////////////////////////////////////////////////////////////////
  1680. void CRopeRenderNode::SetPoints(const Vec3* pPoints, int nCount)
  1681. {
  1682.         m_points.resize(nCount);
  1683.         m_physicsPoints.resize(nCount);
  1684.         if (nCount > 0)
  1685.         {
  1686.                 m_localBounds.Reset();
  1687.                 for (int i = 0; i < nCount; i++)
  1688.                 {
  1689.                         m_points[i] = pPoints[i];
  1690.                         m_physicsPoints[i] = pPoints[i];
  1691.                         m_localBounds.Add(pPoints[i]);
  1692.                 }
  1693.         }
  1694.         float r = m_params.fThickness;
  1695.         m_localBounds.min -= Vec3(r, r, r);
  1696.         m_localBounds.max += Vec3(r, r, r);
  1697.         m_WSBBox.SetTransformedAABB(m_worldTM, m_localBounds);
  1698.  
  1699.         Get3DEngine()->RegisterEntity(this);
  1700.         m_bNeedToReRegister = false;
  1701.  
  1702.         Physicalize();
  1703.         m_bModified = true;
  1704.  
  1705.         if (m_pPhysicalEntity)
  1706.         {
  1707.                 // Awake on first render after modification.
  1708.                 //pe_action_awake pa;
  1709.                 //pa.bAwake = 1;
  1710.                 //m_pPhysicalEntity->Action( &pa );
  1711.         }
  1712. }
  1713.  
  1714. //////////////////////////////////////////////////////////////////////////
  1715. int CRopeRenderNode::GetPointsCount() const
  1716. {
  1717.         return (int)m_points.size();
  1718. }
  1719.  
  1720. //////////////////////////////////////////////////////////////////////////
  1721. const Vec3* CRopeRenderNode::GetPoints() const
  1722. {
  1723.         if (!m_points.empty())
  1724.                 return &m_points[0];
  1725.         else
  1726.                 return 0;
  1727. }
  1728.  
  1729. //////////////////////////////////////////////////////////////////////////
  1730. void CRopeRenderNode::ResetPoints()
  1731. {
  1732.         m_physicsPoints = m_points;
  1733.  
  1734.         Physicalize();
  1735.         m_bModified = true;
  1736. }
  1737.  
  1738. void CRopeRenderNode::OnPhysicsPostStep()
  1739. {
  1740.         // Re-register entity.
  1741.         if (m_bNeedToReRegister)
  1742.         {
  1743.                 pe_params_bbox pbb;
  1744.                 m_pPhysicalEntity->GetParams(&pbb);
  1745.                 m_WSBBox = AABB(pbb.BBox[0], pbb.BBox[1]);
  1746.                 Get3DEngine()->RegisterEntity(this);
  1747.         }
  1748.         m_bNeedToReRegister = false;
  1749.         m_bModified = true;
  1750.  
  1751.         // Update the sound data
  1752.         UpdateSound();
  1753. }
  1754.  
  1755. //////////////////////////////////////////////////////////////////////////
  1756. void CRopeRenderNode::UpdateSound()
  1757. {
  1758.         REINST(update)
  1759.         //if (m_ropeSoundData.nSoundID != INVALID_SOUNDID)
  1760.         //{
  1761.         //      _smart_ptr<ISound> const pSound = gEnv->pAudioSystem->GetSound( m_ropeSoundData.nSoundID );
  1762.         //      if (pSound)
  1763.         //      {
  1764.         //              // Rope is moving, therefore update the sound now
  1765.         //              // Get rope data
  1766.         //              pe_params_rope oRopeParams;
  1767.         //              m_pPhysicalEntity->GetParams( &oRopeParams );
  1768.  
  1769.         //              int nIndexToUse = m_ropeSoundData.nSegementToAttachTo-1;
  1770.         //              Vec3 v3SoundPos = oRopeParams.pPoints[nIndexToUse];
  1771.  
  1772.         //              // Calculate an offset if set
  1773.         //              if (m_ropeSoundData.fOffset > 0.0f)
  1774.         //              {
  1775.         //                      if (m_ropeSoundData.fOffset == 1.0f)
  1776.         //                      {
  1777.         //                              nIndexToUse     = m_ropeSoundData.nSegementToAttachTo;
  1778.         //                              v3SoundPos      = oRopeParams.pPoints[nIndexToUse];
  1779.         //                      }
  1780.         //                      else
  1781.         //                      {
  1782.         //                              if (m_ropeSoundData.fOffset > 0.5f)
  1783.         //                                      nIndexToUse     = m_ropeSoundData.nSegementToAttachTo;
  1784.  
  1785.         //                              v3SoundPos += (oRopeParams.pPoints[m_ropeSoundData.nSegementToAttachTo] - oRopeParams.pPoints[m_ropeSoundData.nSegementToAttachTo - 1]) * m_ropeSoundData.fOffset;
  1786.         //                      }
  1787.         //              }
  1788.  
  1789.         //              // Calculate the angle between the rope segments we're attached to
  1790.         //              if (nIndexToUse != 0 && nIndexToUse != oRopeParams.nSegments)
  1791.         //              {
  1792.         //                      // Do this only if we're not attached to either end
  1793.         //                      Vec3 v3Segment1 = oRopeParams.pPoints[nIndexToUse] - oRopeParams.pPoints[nIndexToUse - 1];
  1794.         //                      Vec3 v3Segment2 = oRopeParams.pPoints[nIndexToUse] - oRopeParams.pPoints[nIndexToUse + 1];
  1795.         //                      v3Segment1.Normalize();
  1796.         //                      v3Segment2.Normalize();
  1797.  
  1798.         //                      float const fAngle = RAD2DEG( acosf( max( -1.0f, v3Segment1.Dot( v3Segment2 ) ) ) );
  1799.  
  1800.         //                      // Update the angle parameter (min 0 max 180 in degree)
  1801.         //                      pSound->SetParam( "angle", fAngle );
  1802.         //              }
  1803.  
  1804.         //              // Update position
  1805.         //              pSound->SetPosition( v3SoundPos );
  1806.         //      }
  1807.         //}
  1808. }
  1809.  
  1810. //////////////////////////////////////////////////////////////////////////
  1811. void CRopeRenderNode::SetRopeSound(char const* const pcSoundName, int unsigned const nSegmentToAttachTo, float const fOffset)
  1812. {
  1813.         REINST(set spund)
  1814.         //m_ropeSoundData.nSegementToAttachTo   = nSegmentToAttachTo;
  1815.         //m_ropeSoundData.fOffset                                                       = fOffset;
  1816.  
  1817.         //if (pcSoundName && pcSoundName[0])
  1818.         //{
  1819.         //      bool bAlreadyExists = false;
  1820.  
  1821.         //      // Stop a potentially already existing sound
  1822.         //      if (m_ropeSoundData.nSoundID != INVALID_SOUNDID)
  1823.         //      {
  1824.         //              _smart_ptr<ISound> const pOldSound = gEnv->pAudioSystem->GetSound( m_ropeSoundData.nSoundID );
  1825.         //              if (pOldSound)
  1826.         //              {
  1827.         //                      // Make sure we don't create a new sound if we already loaded the passed one
  1828.         //                      char const* const pcName = pOldSound->GetName();
  1829.         //                      if (pcName!=0 && _stricmp(pcName, pcSoundName))
  1830.         //                              StopRopeSound();
  1831.         //                      else
  1832.         //                      {
  1833.         //                              bAlreadyExists = true;
  1834.         //                              ResetRopeSound();
  1835.         //                      }
  1836.         //              }
  1837.         //      }
  1838.  
  1839.         //      if (!bAlreadyExists)
  1840.         //      {
  1841.         //              // Now create the new one
  1842.         //              int const nSoundFlags = FLAG_SOUND_DEFAULT_3D|FLAG_SOUND_EVENT|FLAG_SOUND_LOAD_SYNCHRONOUSLY;
  1843.         //              _smart_ptr<ISound> const pNewSound = gEnv->pAudioSystem->CreateSound( pcSoundName, nSoundFlags );
  1844.         //              if (pNewSound)
  1845.         //              {
  1846.         //                      m_ropeSoundData.nSoundID = pNewSound->GetId();
  1847.         //                      pNewSound->SetSemantic( eSoundSemantic_Physics_General );
  1848.         //                      ResetRopeSound();
  1849.         //                      pNewSound->Play();
  1850.         //              }
  1851.         //      }
  1852.         //}
  1853. }
  1854.  
  1855. //////////////////////////////////////////////////////////////////////////
  1856. void CRopeRenderNode::StopRopeSound()
  1857. {
  1858.         REINST(stop sound)
  1859.         //if (m_ropeSoundData.nSoundID != INVALID_SOUNDID)
  1860.         //{
  1861.         //      _smart_ptr<ISound> const pSound = gEnv->pAudioSystem->GetSound( m_ropeSoundData.nSoundID );
  1862.         //      if (pSound)
  1863.         //              pSound->Stop();
  1864.  
  1865.         //      m_ropeSoundData.nSoundID = INVALID_SOUNDID;
  1866.         //}
  1867. }
  1868.  
  1869. //////////////////////////////////////////////////////////////////////////
  1870. void CRopeRenderNode::ResetRopeSound()
  1871. {
  1872.         REINST(reset sound)
  1873.         //if (m_ropeSoundData.nSoundID != INVALID_SOUNDID)
  1874.         //{
  1875.         //      _smart_ptr<ISound> const pSound = gEnv->pAudioSystem->GetSound( m_ropeSoundData.nSoundID );
  1876.         //      if (pSound)
  1877.         //      {
  1878.         //              // Get rope data
  1879.         //              pe_params_rope oRopeParams;
  1880.         //              m_pPhysicalEntity->GetParams( &oRopeParams );
  1881.  
  1882.         //              int nIndexToUse = m_ropeSoundData.nSegementToAttachTo-1;
  1883.         //              Vec3 v3SoundPos = oRopeParams.pPoints[nIndexToUse];
  1884.  
  1885.         //              // Calculate an offset if set
  1886.         //              if (m_ropeSoundData.fOffset > 0.0f)
  1887.         //              {
  1888.         //                      if (m_ropeSoundData.fOffset == 1.0f)
  1889.         //                      {
  1890.         //                              nIndexToUse     = m_ropeSoundData.nSegementToAttachTo;
  1891.         //                              v3SoundPos      = oRopeParams.pPoints[nIndexToUse];
  1892.         //                      }
  1893.         //                      else
  1894.         //                      {
  1895.         //                              if (m_ropeSoundData.fOffset > 0.5f)
  1896.         //                                      nIndexToUse     = m_ropeSoundData.nSegementToAttachTo;
  1897.  
  1898.         //                              v3SoundPos += (oRopeParams.pPoints[m_ropeSoundData.nSegementToAttachTo] - oRopeParams.pPoints[m_ropeSoundData.nSegementToAttachTo - 1]) * m_ropeSoundData.fOffset;
  1899.         //                      }
  1900.         //              }
  1901.  
  1902.         //              // Update position
  1903.         //              pSound->SetPosition( v3SoundPos );
  1904.         //              pSound->SetParam( "angle", 180.0f );
  1905.         //      }
  1906.         //}
  1907.  
  1908. }
  1909.  
  1910. ///////////////////////////////////////////////////////////////////////////////
  1911. void CRopeRenderNode::OffsetPosition(const Vec3& delta)
  1912. {
  1913.         if (m_pTempData) m_pTempData->OffsetPosition(delta);
  1914.         m_pos += delta;
  1915.         m_worldTM.SetTranslation(m_pos);
  1916.         m_InvWorldTM = m_worldTM.GetInverted();
  1917.         m_WSBBox.Move(delta);
  1918.  
  1919.         if (m_pPhysicalEntity)
  1920.         {
  1921.                 pe_status_pos status_pos;
  1922.                 m_pPhysicalEntity->GetStatus(&status_pos);
  1923.  
  1924.                 pe_params_pos par_pos;
  1925.                 par_pos.pos = status_pos.pos + delta;
  1926.                 par_pos.bRecalcBounds = 3;
  1927.                 m_pPhysicalEntity->SetParams(&par_pos);
  1928.         }
  1929. }
  1930.  
  1931. ///////////////////////////////////////////////////////////////////////////////
  1932. void CRopeRenderNode::FillBBox(AABB& aabb)
  1933. {
  1934.         aabb = CRopeRenderNode::GetBBox();
  1935. }
  1936.  
  1937. ///////////////////////////////////////////////////////////////////////////////
  1938. EERType CRopeRenderNode::GetRenderNodeType()
  1939. {
  1940.         return eERType_Rope;
  1941. }
  1942.  
  1943. ///////////////////////////////////////////////////////////////////////////////
  1944. float CRopeRenderNode::GetMaxViewDist()
  1945. {
  1946.         if (GetMinSpecFromRenderNodeFlags(m_dwRndFlags) == CONFIG_DETAIL_SPEC)
  1947.                 return max(GetCVars()->e_ViewDistMin, CRopeRenderNode::GetBBox().GetRadius() * GetCVars()->e_ViewDistRatioDetail * GetViewDistRatioNormilized());
  1948.  
  1949.         return(max(GetCVars()->e_ViewDistMin, CRopeRenderNode::GetBBox().GetRadius() * GetCVars()->e_ViewDistRatio * GetViewDistRatioNormilized()));
  1950. }
  1951.  
  1952. ///////////////////////////////////////////////////////////////////////////////
  1953. Vec3 CRopeRenderNode::GetPos(bool bWorldOnly) const
  1954. {
  1955.         return m_pos;
  1956. }
  1957.  
  1958. ///////////////////////////////////////////////////////////////////////////////
  1959. IMaterial* CRopeRenderNode::GetMaterial(Vec3* pHitPos) const
  1960. {
  1961.         return m_pMaterial;
  1962. }
  1963.  
downloadRopeRenderNode.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