BVB Source Codes

CRYENGINE Show ParticleContainer.cpp Source code

Return Download CRYENGINE: download ParticleContainer.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  Created:     24/09/2014 by Filipe amim
  5. //  Description:
  6. // -------------------------------------------------------------------------
  7. //
  8. ////////////////////////////////////////////////////////////////////////////
  9.  
  10. #include "StdAfx.h"
  11. #include "ParticleContainer.h"
  12.  
  13. CRY_PFX2_DBG
  14.  
  15. namespace
  16. {
  17.  
  18. static std::set<void*> g_allocMems;
  19.  
  20. void* ParticleAlloc(size_t sz)
  21. {
  22.         void* ptr = CryModuleMemalign(sz, CRY_PFX2_PARTICLES_ALIGNMENT);
  23.         memset(ptr, 0, sz);
  24.         return ptr;
  25. }
  26.  
  27. void ParticleFree(void* ptr)
  28. {
  29.         CryModuleMemalignFree(ptr);
  30. }
  31.  
  32. }
  33.  
  34. namespace pfx2
  35. {
  36.  
  37. CParticleContainer::CParticleContainer()
  38. {
  39.         Clear();
  40. }
  41.  
  42. CParticleContainer::CParticleContainer(const CParticleContainer& copy)
  43. {
  44.         Clear();
  45. }
  46.  
  47. CParticleContainer::~CParticleContainer()
  48. {
  49.         Clear();
  50. }
  51.  
  52. void CParticleContainer::Resize(size_t newSize)
  53. {
  54.         CRY_PFX2_PROFILE_DETAIL;
  55.  
  56.         if (newSize < m_maxParticles)
  57.                 return;
  58.  
  59.         const size_t newMaxParticles = CRY_PFX2_PARTICLESGROUP_UPPER(newSize + (newSize >> 1)) + 1;
  60.  
  61.         auto prevBuffers = m_pData;
  62.         for (auto type : EParticleDataType::indices())
  63.         {
  64.                 const size_t stride = type.info().typeSize();
  65.                 m_pData[type] = 0;
  66.                 if (m_useData[type] && newMaxParticles > 0)
  67.                         m_pData[type] = ParticleAlloc(newMaxParticles * stride);
  68.         }
  69.  
  70.         for (auto type : EParticleDataType::indices())
  71.         {
  72.                 if (!m_useData[type] && newMaxParticles > 0)
  73.                         continue;
  74.                 const size_t stride = type.info().typeSize();
  75.                 const byte* pSource = reinterpret_cast<byte*>(prevBuffers[type]);
  76.                 byte* pDest = reinterpret_cast<byte*>(m_pData[type]);
  77.                 memcpy(pDest, pSource, m_lastId * stride);
  78.         }
  79.  
  80.         for (auto type : EParticleDataType::indices())
  81.         {
  82.                 if (prevBuffers[type])
  83.                         ParticleFree(prevBuffers[type]);
  84.         }
  85.  
  86.         m_maxParticles = newMaxParticles;
  87. }
  88.  
  89. void CParticleContainer::ResetUsedData()
  90. {
  91.         m_useData.fill(false);
  92. }
  93.  
  94. void CParticleContainer::AddParticleData(EParticleDataType type)
  95. {
  96.         CRY_PFX2_PROFILE_DETAIL;
  97.  
  98.         const size_t allocSize = m_maxParticles * type.info().typeSize();
  99.         uint dim = type.info().dimension;
  100.         for (uint i = 0; i < dim; ++i)
  101.         {
  102.                 m_useData[type + i] = true;
  103.                 if (!m_pData[type + i])
  104.                         m_pData[type + i] = ParticleAlloc(allocSize);
  105.         }
  106. }
  107.  
  108. void CParticleContainer::Trim()
  109. {
  110.         for (auto type : EParticleDataType::indices())
  111.         {
  112.                 if (!m_useData[type] && m_pData[type] != 0)
  113.                 {
  114.                         ParticleFree(m_pData[type]);
  115.                         m_pData[type] = 0;
  116.                 }
  117.         }
  118. }
  119.  
  120. void CParticleContainer::Clear()
  121. {
  122.         CRY_PFX2_PROFILE_DETAIL;
  123.  
  124.         for (auto i : EParticleDataType::indices())
  125.         {
  126.                 if (m_pData[i] != 0)
  127.                         ParticleFree(m_pData[i]);
  128.                 m_pData[i] = 0;
  129.                 m_useData[i] = false;
  130.         }
  131.         m_maxParticles = CRY_PFX2_PARTICLESGROUP_STRIDE;
  132.         m_lastId = 0;
  133.         m_firstSpawnId = 0;
  134.         m_lastSpawnId = 0;
  135.         m_nextSpawnId = 0;
  136. }
  137.  
  138. template<typename TData, typename FnCopy>
  139. ILINE void SwapToEndRemoveTpl(TParticleId lastParticleId, const TParticleId* toRemove, size_t toRemoveCount, TData* pData, size_t stride, FnCopy fnCopy)
  140. {
  141.         const uint finalSize = lastParticleId - toRemoveCount;
  142.         uint end = lastParticleId - 1;
  143.         uint i = 0;
  144.         uint j = toRemoveCount - 1;
  145.         for (; i < toRemoveCount && toRemove[i] < finalSize; ++i, --end)
  146.         {
  147.                 for (; end == toRemove[j]; --j, --end)
  148.                         ;
  149.                 fnCopy(pData + stride * toRemove[i], pData + stride * end, stride * sizeof(TData));
  150.         }
  151. }
  152.  
  153. void SwapToEndRemove(TParticleId lastParticleId, const TParticleId* toRemove, size_t toRemoveCount, void* pData, size_t stride)
  154. {
  155.         auto copyFn = [](uint8* pDest, uint8* pSrc, uint stride)
  156.         {
  157.                 memcpy(pDest, pSrc, stride);
  158.         };
  159.         SwapToEndRemoveTpl(
  160.           lastParticleId, toRemove, toRemoveCount,
  161.           reinterpret_cast<uint8*>(pData), stride, copyFn);
  162. }
  163.  
  164. void SwapToEndRemoveStride1(TParticleId lastParticleId, const TParticleId* toRemove, size_t toRemoveCount, void* pData)
  165. {
  166.         auto copyFn = [](uint8* pDest, uint8* pSrc, uint stride)
  167.         {
  168.                 *pDest = *pSrc;
  169.         };
  170.         SwapToEndRemoveTpl(
  171.           lastParticleId, toRemove, toRemoveCount,
  172.           reinterpret_cast<uint8*>(pData), 1, copyFn);
  173. }
  174.  
  175. void SwapToEndRemoveStride4(TParticleId lastParticleId, const TParticleId* toRemove, size_t toRemoveCount, void* pData)
  176. {
  177.         auto copyFn = [](uint32* pDest, uint32* pSrc, uint stride)
  178.         {
  179.                 *pDest = *pSrc;
  180.         };
  181.         SwapToEndRemoveTpl(
  182.           lastParticleId, toRemove, toRemoveCount,
  183.           reinterpret_cast<uint32*>(pData), 1, copyFn);
  184. }
  185.  
  186. void SwapToEndRemoveStride8(TParticleId lastParticleId, const TParticleId* toRemove, size_t toRemoveCount, void* pData)
  187. {
  188.         auto copyFn = [](uint64* pDest, uint64* pSrc, uint stride)
  189.         {
  190.                 *pDest = *pSrc;
  191.         };
  192.         SwapToEndRemoveTpl(
  193.           lastParticleId, toRemove, toRemoveCount,
  194.           reinterpret_cast<uint64*>(pData), 1, copyFn);
  195. }
  196.  
  197. void CParticleContainer::AddParticle()
  198. {
  199.         SSpawnEntry entry = { 1 };
  200.         AddRemoveParticles(&entry, 1, 0, 0);
  201. }
  202.  
  203. void CParticleContainer::AddRemoveParticles(const SSpawnEntry* pSpawnEntries, size_t numSpawnEntries, const TParticleIdArray* pToRemove, TParticleIdArray* pSwapIds)
  204. {
  205.         CRY_PFX2_PROFILE_DETAIL;
  206.  
  207.         size_t newSize = m_lastId;
  208.         if (pToRemove)
  209.                 newSize -= pToRemove->size();
  210.         if (pSpawnEntries)
  211.         {
  212.                 for (size_t entryIdx = 0; entryIdx < numSpawnEntries; ++entryIdx)
  213.                 {
  214.                         const SSpawnEntry& spawnEntry = pSpawnEntries[entryIdx];
  215.                         newSize += spawnEntry.m_count;
  216.                 }
  217.         }
  218.         newSize = CRY_PFX2_PARTICLESGROUP_UPPER(newSize) + CRY_PFX2_PARTICLESGROUP_STRIDE + 1;
  219.         Resize(newSize);
  220.  
  221.         if (pToRemove && !pToRemove->empty())
  222.         {
  223.                 if (pSwapIds && !pSwapIds->empty())
  224.                         MakeSwapIds(*pToRemove, pSwapIds);
  225.                 RemoveParticles(*pToRemove);
  226.         }
  227.  
  228.         if (pSpawnEntries && numSpawnEntries)
  229.                 AddParticles(pSpawnEntries, numSpawnEntries);
  230.         else
  231.                 m_firstSpawnId = m_lastSpawnId = m_lastId;
  232. }
  233.  
  234. void CParticleContainer::AddParticles(const SSpawnEntry* pSpawnEntries, size_t numSpawnEntries)
  235. {
  236.         CRY_PFX2_PROFILE_DETAIL;
  237.  
  238.         m_firstSpawnId = m_lastSpawnId = CRY_PFX2_PARTICLESGROUP_UPPER(m_lastId) + 1;
  239.         uint32 currentId = m_firstSpawnId;
  240.         for (size_t entryIdx = 0; entryIdx < numSpawnEntries; ++entryIdx)
  241.         {
  242.                 const SSpawnEntry& spawnEntry = pSpawnEntries[entryIdx];
  243.                 const size_t toAddCount = spawnEntry.m_count;
  244.  
  245.                 if (HasData(EPDT_ParentId))
  246.                 {
  247.                         TParticleId* pParentIds = GetData<TParticleId>(EPDT_ParentId);
  248.                         for (uint32 i = currentId; i < currentId + toAddCount; ++i)
  249.                                 pParentIds[i] = spawnEntry.m_parentId;
  250.                 }
  251.  
  252.                 if (HasData(EPDT_SpawnId))
  253.                 {
  254.                         uint32* pSpawnIds = GetData<TParticleId>(EPDT_SpawnId);
  255.                         for (uint32 i = currentId; i < currentId + toAddCount; ++i)
  256.                                 pSpawnIds[i] = m_nextSpawnId++;
  257.                 }
  258.                 else
  259.                 {
  260.                         m_nextSpawnId += toAddCount;
  261.                 }
  262.  
  263.                 if (HasData(EPDT_NormalAge))
  264.                 {
  265.                         // Store newborn ages
  266.                         float age = spawnEntry.m_ageBegin;
  267.                         float* pNormalAges = GetData<float>(EPDT_NormalAge);
  268.                         for (uint32 i = currentId; i < currentId + toAddCount; ++i, age += spawnEntry.m_ageIncrement)
  269.                                 pNormalAges[i] = age;
  270.                 }
  271.  
  272.                 if (HasData(EPDT_SpawnFraction))
  273.                 {
  274.                         float fraction = spawnEntry.m_fractionBegin;
  275.                         float* pSpawnFractions = GetData<float>(EPDT_SpawnFraction);
  276.                         for (uint32 i = currentId; i < currentId + toAddCount; ++i, fraction += spawnEntry.m_fractionCounter)
  277.                                 pSpawnFractions[i] = min(fraction, 1.0f);
  278.                 }
  279.  
  280.                 currentId += toAddCount;
  281.                 m_lastSpawnId += toAddCount;
  282.         }
  283. }
  284.  
  285. void CParticleContainer::RemoveParticles(const TParticleIdArray& toRemove)
  286. {
  287.         CRY_PFX2_PROFILE_DETAIL;
  288.  
  289.         const TParticleId lastParticleId = GetLastParticleId();
  290.         const uint toRemoveCount = toRemove.size();
  291.  
  292.         for (auto dataTypeId : EParticleDataType::indices())
  293.         {
  294.                 const uint stride = dataTypeId.info().typeSize();
  295.                 void* pData = m_pData[dataTypeId];
  296.                 if (!m_useData[dataTypeId])
  297.                         continue;
  298.                 switch (stride)
  299.                 {
  300.                 case 1:
  301.                         SwapToEndRemoveStride1(lastParticleId, &toRemove[0], toRemoveCount, m_pData[dataTypeId]);
  302.                         break;
  303.                 case 4:
  304.                         SwapToEndRemoveStride4(lastParticleId, &toRemove[0], toRemoveCount, m_pData[dataTypeId]);
  305.                         break;
  306.                 case 8:
  307.                         SwapToEndRemoveStride8(lastParticleId, &toRemove[0], toRemoveCount, m_pData[dataTypeId]);
  308.                         break;
  309.                 default:
  310.                         SwapToEndRemove(lastParticleId, &toRemove[0], toRemoveCount, m_pData[dataTypeId], stride);
  311.                 }
  312.         }
  313.  
  314.         m_lastId -= toRemoveCount;
  315. }
  316.  
  317. void CParticleContainer::MakeSwapIds(const TParticleIdArray& toRemove, TParticleIdArray* pSwapIds)
  318. {
  319.         CRY_PFX2_PROFILE_DETAIL;
  320.  
  321.         const TParticleId lastParticleId = GetLastParticleId();
  322.         const uint toRemoveCount = toRemove.size();
  323.         const uint finalSize = lastParticleId - toRemoveCount;
  324.         auto& swapIds = *pSwapIds;
  325.         CRY_PFX2_ASSERT(uint(swapIds.size()) >= lastParticleId);    // swapIds not big enough
  326.  
  327.         for (size_t j = 0; j < lastParticleId; ++j)
  328.                 swapIds[j] = j;
  329.  
  330.         SwapToEndRemoveStride4(lastParticleId, &toRemove[0], toRemoveCount, swapIds.data());
  331.         for (uint i = finalSize; i < lastParticleId; ++i)
  332.                 swapIds[i] = gInvalidId;
  333.  
  334.         for (uint i = 0; i < finalSize; ++i)
  335.         {
  336.                 TParticleId v0 = swapIds[i];
  337.                 TParticleId v1 = swapIds[v0];
  338.                 swapIds[i] = v1;
  339.                 swapIds[v0] = i;
  340.         }
  341. }
  342.  
  343. void CParticleContainer::ResetSpawnedParticles()
  344. {
  345.         CRY_PFX2_PROFILE_DETAIL;
  346.  
  347.         CRY_PFX2_ASSERT(m_firstSpawnId >= m_lastId);
  348.  
  349.         const uint numSpawn = GetNumSpawnedParticles();
  350.         const uint gapSize = m_firstSpawnId - m_lastId;
  351.         const uint movingId = m_lastSpawnId - min(gapSize, numSpawn);
  352.         if (gapSize != 0)
  353.         {
  354.                 for (auto dataTypeId : EParticleDataType::indices())
  355.                 {
  356.                         const size_t stride = dataTypeId.info().typeSize();
  357.                         byte* pBytes = reinterpret_cast<byte*>(m_pData[dataTypeId]);
  358.                         if (!pBytes)
  359.                                 continue;
  360.                         memcpy(pBytes + m_lastId * stride, pBytes + movingId * stride, gapSize * stride);
  361.                 }
  362.         }
  363.  
  364.         m_lastId = m_lastSpawnId - gapSize;
  365.         m_firstSpawnId = m_lastSpawnId = m_lastId;
  366. }
  367.  
  368. void CParticleContainer::RemoveNewBornFlags()
  369. {
  370.         void* pBegin = m_pData[EPDT_State];
  371.         void* pCursor = pBegin;
  372.  
  373. #ifdef CRY_PFX2_USE_SSE
  374.         const __m128i flag128 = _mm_set1_epi8(~ESB_NewBorn);
  375.         __m128i* pBegin128 = static_cast<__m128i*>(pCursor);
  376.         __m128i* pEnd128 = static_cast<__m128i*>(pBegin) + m_lastId / sizeof(__m128i);
  377.         for (; pBegin128 != pEnd128; ++pBegin128)
  378.                 *pBegin128 = _mm_and_si128(*pBegin128, flag128);
  379.         pCursor = pEnd128;
  380. #endif
  381.  
  382.         const uint8 mask = ~ESB_NewBorn;
  383.         const uint32 flag32 = (mask << 24) | (mask << 16) | (mask << 8) | mask;
  384.         uint32* pBegin32 = static_cast<uint32*>(pCursor);
  385.         uint32* pEnd32 = static_cast<uint32*>(pBegin) + m_lastId / sizeof(uint32);
  386.         for (; pBegin32 != pEnd32; ++pBegin32)
  387.                 *pBegin32 &= flag32;
  388.         pCursor = pEnd32;
  389.  
  390.         uint8* pBegin8 = static_cast<uint8*>(pCursor);
  391.         uint8* pEnd8 = static_cast<uint8*>(pBegin) + m_lastId / sizeof(uint8);
  392.         for (; pBegin8 != pEnd8; ++pBegin8)
  393.                 *pBegin8 &= mask;
  394. }
  395.  
  396. }
  397.  
downloadParticleContainer.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